You are on page 1of 77

P OLITECHNIKA WARSZAWSKA

W YDZIAŁ F IZYKI
Z AKŁAD F IZYKI J ADROWEJ
˛

P RACA IN ŻYNIERSKA

Oprogramowanie ćwiczenia
“Badanie efektu Comptona”
Software developement for “Compton
Effect” excercise

Jacek Bzdak
nr. albumu: 196909

Promotor: dr inż. Przemysław Duda

WARSZAWA 2009
The first 90% of the code accounts for the first
90% of the development time. The remaining
10% of the code accounts for the other 90% of
the development time.

Tom Cargill
On two occasions I have been asked, ’Pray, Mr.
Babbage, if you put into the machine wrong
figures, will the right answers come out?’ I am
not able rightly to apprehend the kind of
confusion of ideas that could provoke such a
question.

Charles Babbage
Defensive programming? Never! Klingon
programs are always on the offense. Yes,
Offensive programming is what we do best

Klingons programmer manual


http://www.sjbaker.org/humor/klingon_
programmer.html
To know when enough is enough
is enough to know

Lao Tzu Tao te cing, a book about the way, and


the power of the way, tłum Ursula K. Le Guin

ii
Streszczenie

Celem niniejszej pracy jest uruchomienie ćwiczenia “Eksperyment


Comptona” w Laboratorium Fizyki i Technik Jadrowych.
˛ W ramach
pracy powstała aplikacja pozwalajaca
˛ przeprowadzić ćwiczenie. Główna˛
cz˛eścia˛ pracy jest opis powstałego oprogramowania, składajacy
˛ si˛e
z opisu samego kodu, technologii i bibliotek z którymi program współ-
pracuje, czy wreszcie opisu procedur budowania i modyfikowania kodu
źródłowego.
Rozdział pierwszy zawiera wstep
˛ teoretyczny. Wyprowadzono wzory
opisujace
˛ zależności energetyczne oraz podano wzór Kleina–Nishiny
na przekrój czynny w efekcie Comptona. Rozdział zawiera też rys his-
toryczny zawierajacy
˛ opis układu pomiarowego, z którego korzystał
i wyników jakie otrzymał A. Compton w swoim uhonorowanym na-
groda˛ Nobla eksperymencie. Rozdział zawiera też wyniki modelowania
eksperymentu uzyskane z cz˛eści symulacyjnej programu oraz (dla
porównania) przekroje zawarte w literaturze.
Rozdział drugi zawiera opis urzadze
˛ ń elektronicznych stanowiacych
˛
tory spektrometryczne. Układ został zestawiony w oparciu o sprz˛et firmy
Canberra. Zdarzenia jadrowe
˛ rejestrowane sa˛ za pomoca˛ detektorów
scyncylacyjnych NaI; sygnały z tych detektorów po wzmocnieniu trafiaja˛
do podłaczonego
˛ do układu koincydencyjnego urzadzenia
˛ Multiport, 2
pełniacego
˛ role˛ ADC i analizatora wielokanałowego.
Rozdział trzeci zawiera opis stworzonego oprogramowania. Program
składa si˛e z dwóch cześci:
˛ symulacji eksperymentu oraz oprogramowa-
nia rzeczywiście przeprowadzajacego
˛ eksperyment. Symulacja jest zro-
biona w ten sposób, że może działać zarówno jako samodzielna ap-
likacja, jak i aplet b˛edacy
˛ cz˛eścia˛ strony internetowej. Rozdział ten
zawiera też podstawowe informacje o systemie Maven, który jest uży-
wany do zarzadzania
˛ zależnościami oraz budowy gotowego programu.
Rozdział czwarty zawiera instrukcje budowania programu za pomoca˛
systemu maven oraz procedure˛ instalacji samego mavena. Instalacja
systemu maven nie jest trudna, jednak szczególnie w systemie Windows,
może wymagać dodatkowych wyjaśnień. W rozdziale tym opisano też
strukture˛ programu oraz opisano procedury edycji kodu źródłowego
programu w trzech podstawowych środowiskach programistycznych
(Intelij Idea, Eclipse i NetBeans).

iii
Abstract

The aim of the B.Sc thesis is to initiate the exercise “Compton’s


Experiment” in the Laboratory of Nuclear Physics and techniques.
Within this B.SC thesis an application was created which allows to
carry out the exercise. The main point of the paper itself is a description
of the software created, it comprises the description the code itself,
technology and the libraries with which the software collaborates, and
finally, the procedures of building and modifying the source code.
Chapter One opens with a theoretical introduction. The formulas
describing energetic relations were introduced simultaneously with
a Klein-Nishina formula for cross–section in a Compton effect. This
Chapter comprises also a historical draft containing description of
a measuring set used by A. Compton and the results he had obtained
for which he was awarded a Nobel Price. The Chapter includes also
the results of the experiment’s modelling obtained from a simulation
part of the software, and, in comparison, cross–sections taken from
respective literature.
Chapter Two comprises the description of spectrometric equipement.
Equipement was built from modules provided by Canberra. Nuclear
collisions are registered by scincillation (NaI) detectors. Reinforced
signals, emited from these detectors, meet Multiport 2 device which
acts both as ADC and multi–chanelle analyser.
Chapter Three comprises the description of a software created. The
software consists of two parts: the first part of the software refers to
the simulation of the experiment; the second one refers to the software
actually conducting the experiment. The simulation is created in a way
that it can act independently, or can function as an aplet of a given
website. The Chapter comprises also basic information on the Maven
system used in a dependencies management, and in building of the
software
Chapter Four comprises the instruction how to build a software
with the use of the Maven system, and the procedure of Maven’ s in-
stallation as well. The installation of the Maven system does not appear
to be much complicated, though it may need additional information,
especially in the Windows system. The structure of the software is also
described in this Chapter, as well as the procedures of the edition of the
software source code in three main integrated software environments.

iv
Spis treści

Spis treści v

Wstep
˛ vii

1 Eksperyment Comptona 1
1.1 Fizyka doświadczenia . . . . . . . . . . . . . . . . . . . . . 1
1.2 Oryginalny układ pomiarowy . . . . . . . . . . . . . . . . . 3
1.3 Wyniki Comptona . . . . . . . . . . . . . . . . . . . . . . . 4

2 Tor spektrometryczny 8
2.1 Cześć
˛ mechaniczna . . . . . . . . . . . . . . . . . . . . . . 8
2.2 Opis urzadze
˛ ń . . . . . . . . . . . . . . . . . . . . . . . . . 9

3 Opis programu 12
3.1 Architektura . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.2 Moduły programu . . . . . . . . . . . . . . . . . . . . . . . 12
3.3 Opis systemu Maven . . . . . . . . . . . . . . . . . . . . . 13
3.4 Moduł dies-irae:dies-irae . . . . . . . . . . . . . . . . 15
3.5 Moduł dies-irae:dies-assembly . . . . . . . . . . . . . 18
3.6 Moduł dies-irae:dies-config . . . . . . . . . . . . . . 20
3.7 Moduł dies-irae:encore-silniki . . . . . . . . . . . . 21
3.8 Moduł genie-connector . . . . . . . . . . . . . . . . . . . 25
3.9 Moduł encore-symulacja . . . . . . . . . . . . . . . . . . 41
3.10 Moduł dies-gui . . . . . . . . . . . . . . . . . . . . . . . . 42
3.11 Moduł dies-peakfinder . . . . . . . . . . . . . . . . . . . 45

4 Dystrybucja programu 47
4.1 Struktura projektu . . . . . . . . . . . . . . . . . . . . . . . 47
4.2 Budowanie projektu . . . . . . . . . . . . . . . . . . . . . . 47
4.3 Struktura gotowego programu . . . . . . . . . . . . . . . . 48
4.4 Edycja projektu . . . . . . . . . . . . . . . . . . . . . . . . 48
4.5 Wymagania projektu . . . . . . . . . . . . . . . . . . . . . 50

5 Eksperyment 52
5.1 Cele ćwiczenia . . . . . . . . . . . . . . . . . . . . . . . . . 52
5.2 Przykładowe sprawozdanie . . . . . . . . . . . . . . . . . . 52
5.3 Peryspektywy rozwoju . . . . . . . . . . . . . . . . . . . . . 56

Bibliografia 65

v
Spis rysunków 67

Załaczniki
˛ 69
Słownik terminów programistycznych . . . . . . . . . . . . . . 69
Oznaczenia na diagramach UML . . . . . . . . . . . . . . . . . 69

vi
Wstep
˛

Celem pracy było uruchomienie ćwiczenia “Eksperyment Comptona”


w Laboratorium Fizyki i Technik Jadrowych.
˛ Eksperyment Comptona
był jednym z przełomowych eksperymentów w historii Fizyki — sam
efekt Comptona był niewytłumaczalny w ramach teorii klasycznej.
W bieżacym
˛ układzie sprz˛etowym ćwiczenie to zapozna studentów
z metoda˛ kalibracji detektorów scyntylacyjnych, technika˛ pomiarów
koincydencyjnych, pokaże zasade˛ zachowania energii ’w działaniu’,
czy wreszcie pozwoli jakościowo zbadać przekroje czynne na efekt
Comptona.
Praca ta jest praca˛ interdyscyplinarna˛ fizyka — informatyka.
Aparatura pomiarowa składa sie˛ z detektorów scyntylacyjnych NaI
oraz modłów NIM przetwarzajacych ˛ sygnały z detektorów. Wszystkie
elementy torów spektrometrycznych zostały dostarczone przez Can-
berre˛ . Ponieważ szyna NIM dostarcza tylko napi˛ecie i nie pośredniczy
w komunikacji, cała komunikacja miedzy ˛ nimi jest analogowa. Z kom-
puterem komunikuje si˛e moduł “Multiport 2”, zawierajacy ˛ dwa konwert-
ery analog–cyfra oraz dwa analizatory wielokanałowe (1024 kanały);
komunikacja ta odbywa sie˛ za pośrednictwem portu USB.
Całość oprogramowania została stworzona w Javie. Java jest jednym
z najbardziej dojrzałych obecnych na rynku j˛ezyków programowania.
Java została wybrana z kilku powodów — po pierwsze cz˛eści tej ap-
likacji bed
˛ a˛ udostepniane
˛ przez internet, a tylko Java umożliwia łatwe
uruchamianie tego samego kodu zarówno w środowisku aplikacji, jak
i w środowisku webowym, po drugie — autor posiada duże doświad-
czenie w programowaniu w tym jezyku ˛ programowania. W tej aplikacji
nie korzystamy z głównej zalety Javy — jej przenośności, ponieważ
biblioteki służace
˛ do komunikacji z osprz˛etem Canberry dostarczane
sa˛ tylko w wersji dla systemu operacyjnego Windows.

vii
Rozdział 1

Eksperyment Comptona

Eksperyment Comptona był jednym z pierwszych eksperymentów


wykazujacych
˛ kwantowa˛ nature˛ światła. Doniosłość tego eksperymentu
potwierdza fakt przyznania za niego nagrody Nobla w 1927 roku.
W ramach teorii falowych uznawano, że mechanizm rozpraszania
światła jest nast˛epujacy:
˛ fala świetlna pada na elektron pobudzajac ˛
go do drgań, elektron nast˛epnie drgajac ˛ wypromieniowuje fal˛e o tej
samej cz˛estotliwości. Model ten był zgodny z doświadczeniem dla fal
świetlnych – fal o małych cz˛estotliwościach, natomiast dla promieni
X i γ okazywał sie˛ niedostatecznym.

1.1 Fizyka doświadczenia


Wyjaśnieniem efektu Comptona jest uznanie padajacej˛ wiazki
˛ pro-
mieni za zbiór kwantów o energii E = hν, które podlegaja˛ spre˛ żystemu
zderzeniu z elektronami na orbitach walencyjnych1 [1].
1 Elektrony te maja˛ tak mała˛ energie
˛ wiazania,
˛ że można je praktycznie uznać za
elektrony swobodne.

Rysunek 1.1: Geometria zderzenia comptonowskiego. Opracowanie


własne.

1
Zderzenie opisuja˛ nastepuj
˛ ace
˛ zasady zachowania pedu
˛ i energii:

pγ = pγ‘ + pβ 0 (1.1)

Eγ + Eβ = Eγ‘ + Eβ 0 (1.2)
gdzie 1.1 jest równaniem wektorowym, γ oznacza padajacy ˛ kwant
gamma, γ 0 oznacza rozproszony kwant gamma, β oznacza elektron,
na jakim rozpraszanie si˛e odbywa2 , natomiast β 0 to elektron rozpros-
zony.

Zależności energetyczne
Energie wyrażaja˛ sie˛ wzorami:

Eγ = hν
Eγ 0 = hν 0
Eβ = m0 c2 (1.3)
q
Eβ 0 = (pβ c)2 + (m0 c2 )2

Podstawiajac
˛ do równania 1.2 wzory na energi˛e (równanie 1.3) otrzy-
mujemy:
q
hf + m0 c2 = hf 0 + (pβ c)2 + (m0 c2 )2

Po podniesieniu do kwadratu i uporzadkowaniu:


˛

p2β c2 = (hf + m0 c2 − hf 0 )2 − m20 c4 (1.4)

Z zasady zachowania pe˛ du mamy:

pβ = pγ − pγ 0

Wykonajmy iloczyn skalarny p2β

p2β = pβ · pβ
= (pγ − pγ 0 ) · (pγ − pγ 0 )
= pγ2 + pγ20 − 2pγ pγ 0 cos θ.

Po wykorzystaniu równań obowiazuj


˛ acych
˛ dla kwantów gamma: pc = hν
oraz pomnożeniu obu stron równania przez c2 :

p2β c2 = (hν)2 + (hν 0 )2 − 2(hν)(hν 0 ) cos θ. (1.5)

Podstawiajac
˛ równanie 1.4 do 1.5 otrzymujemy:
2 2
(hν + m0 c2 − hν 0 )2 − m02 c4 = (hν) + (hν 0 ) − 2h2 νν 0 cos θ.
2hνme c2 − 2hν 0 me c2 = 2h2 νν 0 (1 − cos θ)

2E to energia spoczynkowa elektronu


β

2
Po podzieleniu obu stron równania przez 2hf f 0 m:

c c h
0
− = (1 − cos θ) .
ν ν m0 c
Po zauważeniu że νλ = c, ostatecznie otrzymujemy:

h
λ0 − λ = (1 − cos θ). (1.6)
m0 c

Przekroje czynne
Z diagramów Feynmana w ramach elektrodynamiki kwantowej mo-
żna wyprowadzić wzory na przekrój czynny efektu w efekcie Comptona.
Wzory te po raz pierwszy wyprowadzili Klein i Nishina.
Wzór Kleina–Nishiny:

dσ 1
= α2 rc2 P (Eγ ,θ)2 (P (Eγ ,θ) + P (Eγ ,θ)−1 − 1 + cos2 (θ)) (1.7)
dΩ 2
Gdzie: α to stała struktury subtelnej3 , θ to kat
˛ rozproszenia kwantu
γ, natomiast P (Eγ ,θ) to iloczyn energii kwantu padajacego˛ i rozpros-
zonego4 .
Wzoru 1.7 nie b˛edziemy wyprowadzać. Pokażemy natomiast prze-
kroje czynne dla kwantów γ i elektronów otrzymane za pomoca˛ apletu
symulujacego
˛ efekt Comptona. Dla porównania na rys 1.5 zamieszczono
te same przekroje z opracowań.
Dla niskich energii (które badał Compton) wartość przekroju czyn-
nego na efekt Comptona dla 0◦ i 180◦ jest praktycznie taka sama, dla
wysokich energii natomiast szansa zajścia efektu jest istotnie wyższa
dla niskich katów.
˛

1.2 Oryginalny układ pomiarowy


Zapoznajmy si˛e z układem pomiarowym z jakiego korzystał A. Comp-
ton. Za pomoca˛ lampy RTG emitujacej ˛ promieniowanie o długości
fali 0.71A (linia Kα molibdenu) oświetlano blok rozpraszajacy ˛ wyko-
nany z grafitu. Rozproszone promieniowanie (po przejściu przez układ
szczelin) trafiało do detektora. Detektor można było ustawić pod katem
˛
wzgl˛edem wiazki˛ padajacej.
˛ Oryginalnie Compton mierzył nat˛eżenie
odbitych promieni X w zależności od ich długości dla różnych katów[2,
˛
str 22]. Układ pomiarowy zaprezentowany jest na rys. 1.6.
3 Jedna z podstawowych stałych fizycznych, można ja˛ wyrazić poprzez inne stałe na

trzy sposoby:
e2 e2 cµ0 ke e2
α= = =
h̄c 4πε0 2h h̄c
jest jednak możliwy jej bezpośredni pomiar.
4 Wyraża sie
˛ on wzorem:
1
P (Eγ ,θ) = Eγ
1+ me c 2
(1 − cos θ)

3
(a) Zależność energii od kata
˛ (b) Zależność energii od kata
˛
rozproszenia dla rozproszonych rozproszenia dla rozproszonych
elektronów kwantów γ

(c) Rozkład katowy


˛ rozproszonych (d) Przekrój czynny dla kwantów γ
elektronów

Rysunek 1.2: Zależności energetyczne i katowe


˛ dla padajacego
˛ kwanta
gamma o energii 0.01M eV . Opracowanie własne.

1.3 Wyniki Comptona


Compton uzyskał zaskakujace, ˛ jak na owe czasy, wyniki (rys 1.7).
Chociaż wiazka
˛ padajaca
˛ zawiera tylko jedna˛ długość fali – wiazka
˛
odbita (dla niezerowych katów)
˛ zawierała dwa piki. Efekt ten był niewy-
jaśniany na gruncie mechaniki klasycznej – w ramach tej teorii fala
odbita musi mieć długość fali padajacej.
˛
Pik odpowiadajacy
˛ niezmienionej długości fali pochodzi ze zderzeń
fotonów z elektronami zwiazanymi
˛ z rdzeniami atomów w˛egla (ich masa
efektywna jest na tyle duża, że przesuni˛ecie Comptonowskie jest dla
nich nieobserwowalne)[2, str 23].

4
(a) Zależność energii od kata
˛ (b) Zależność energii od kata
˛
rozproszenia dla rozproszonych rozproszenia dla rozproszonych
elektronów kwantów γ

(c) Rozkład katowy


˛ rozproszonych (d) Przektój czynny dla kwantów γ
elektronów

Rysunek 1.3: Zależności energetyczne i katowe


˛ dla padajacego
˛ kwanta
gamma o energii 0.660M eV . Opracowanie własne.

5
(a) Zależność energii od kata
˛ (b) Zależność energii od kata
˛
rozproszenia dla rozproszonych rozproszenia dla rozproszonych
elektronów kwantów γ

(c) Rozkład katowy


˛ rozproszonych (d) Przektój czynny dla kwantów γ
elektronów

Rysunek 1.4: Zależności energetyczne i katowe


˛ dla padajacego
˛ kwanta
gamma o energii 1,13M eV . Opracowanie własne.

(a) Rozkład katowy


˛ (b) Przekroje czynne dla kwantów γ w zależności od
rozproszonych elek- energii
tronów w zależności
od energii

Rysunek 1.5: Przekroje czynne i rozkłady katowe


˛ za [1, str 65]

6
Rysunek 1.6: Schemat oryginalnego układu pomiarowego Comptona
[2, rys 16]

(a) Wiazka
˛ nierozproszona (b) Wiazka
˛ rozproszona 45◦

(c) Wiazka
˛ rozproszona 90◦ (d) Wiazka
˛ rozproszona 135◦

Rysunek 1.7: Wyniki Comptona[2, rys 16]

7
Rozdział 2

Tor spektrometryczny

Poszczególne zjawiska jadrowe


˛ rejestrowane sa˛ za pomoca˛ spektrom-
etrycznych liczników scyntylacyjnych NaI (na rys. 2.1). W detektorze
3 zachodzi efekt Comptona, rozproszony kwant gamma opuszcza detek-
tor, natomiast elektron zostanie zarejestrowany przez licznik. Detektor
2 można obracać wokół detektora 3.
Detektory pracuja˛ w układzie koincydencyjnym. Schemat elektron-
icznej cześci
˛ układu na rys. 2.3.
W toku rozwoju doświadczenia lepiej byłoby zamienić nieruchomy
detektor na urzadzenie
˛ oparte na scyntylatorze plastikowym. W tego
typu urzadzeniach
˛ praktycznie nie zachodzi efekt fotoelektryczny, co
powinno obniżyć ilość przypadkowych koincydencji.

2.1 Cześć
˛ mechaniczna
Mechaniczna˛ cz˛eść ukadu zaprojektowano i wykonano w ramach
poprzedniej wersji ćwiczenia, w warsztacie Wydziału Fizyki Politechniki
Warszawskiej. Zdjecie
˛ układu na rys. 2.2.

Rysunek 2.1: Geometria eksperymentu [1]

8
Rysunek 2.2: Zdjecie
˛ mechanicznej cześci
˛ układu wraz z detektorami.

2.2 Opis urzadze


˛ ń
Źródło wysokiego napiecia
˛ 3125 Moduł NIM umożliwiajacy
˛ zasilanie
dwóch urzadze
˛ ń oddzielnie regulowanym napieciem
˛ do 5kV i do 300µA.
[3]

Detektor scyntylacyjny model 802 i Przedwzmacniacz 2007P


Urzadzenia
˛ te sa˛ zaprojektowane do pracy w parze. Detektor scynty-
lacyjny jest połaczony
˛ z przedwzmacniaczem. Do przedwzmacniacza
podłacza
˛ sie˛ wysokie napi˛ecie (pochodzace
˛ z modułu 3125) oraz napie-
˛
cie przedwzmacniacza pochodzace ˛ z modułu 2026 [4, 5]

Wzmacniacz 2026 Zasila przedwzmacniacz modułu 2007P, wzmac-


nia i kształtuje sygnał z detektorów.
Wyjścia:
UNI Udost˛epnia analogowy liniowy przefiltrowany i ukształtowany syg-
nał.
ICR Udost˛epnia logiczny (TTL) sygnał odpowiadajacy
˛ przetwarzaniu
sygnału spektrometrycznego.
Opis z [6].

Analizator koincydencji Analizator koincydencji posiadajacy ˛ 4 wejś-


cia (z których jedno może być zdefiniowane jako antykoincydencyjne).
Pozwala na ustawienie okna koincydencji od 10ns do 1µs.
Wejścia i wyjścia:
INPUT Wejście analizatora, wymaga sygnałów TTL trwajacych
˛ min
100ns narastajacych
˛ przez max 50ns.
OUTPUT Wyjście analizatora. Wysyła sygnał TTL narastajacy
˛ 50ns
i trwajacy
˛ 1µs.

9
Rysunek 2.3: Schemat elektronicznej cz˛eści układu. Dla przejrzys-
tości narysowano tylko jeden tor spektrometryczny, w rzeczywistym
układzie elementy zaznaczone na różowo sa˛ podwojone. W nawiasach
przy nazwach wejść podano typ końcówki przewodu. Opracowanie
własne.

Multiport II Analizator widma mogacy ˛ analizować dane z 2 torów


spektrometrycznych1 Pełni role˛ ADC.
Każdym z torów można sterować elektronicznie za pomoca˛ wejścia
IO. Komunikacj˛e z komputerem zapewnia port USB, Multiport może
być kontrolowany przez program Genie 2000 oraz za pomoca˛ “S560
Programming library”.

IO Port szeregowy (jeden dla każdego toru), pozwalajacy


˛ zarówno kon-
trolować zachowanie Multiportu, jaki i zwracajacy ˛ informacje
o jego stanie. W bieżacym
˛ ustawieniu wykorzystywany jest pin 13
tego portu, do którego podłaczony
˛ jest detektor koincydencji.
ADC IN wejście do konwertera ADC.
1 Można go rozbudować tak, by był wstanie analizować do 6 torów.

10
Silniki krokowe Silnikiem krokowym zarzadza
˛ sie˛ za pomoca˛ sprz˛e-
towego sterownika dostarczonego ze sprzetem
˛ (dokładny opis w para-
grafie 3.7).

11
Rozdział 3

Opis programu

3.1 Architektura
Program podzielono na moduły. Podział ten ma nastepuj
˛ ace
˛ cele:

Podział odpowiedzialności Każdy moduł zajmuje sie˛ jednym logi-


cznym zestawem zadań.
Zmniejszenie working set-u kodu Podczas pracy z jednym modu-
łem programista nie musi myśleć o innych modułach, w ten spo-
sób zmniejszono ilość kodu, jaki musi mieć w pamieci.
˛
Separacja zależności Niektóre moduły nie powinny zależeć od kodu
zawartego w innych modułach1

3.2 Moduły programu


Program składa sie˛ z nastepuj
˛ acych
˛ modułów:

dies-irae:dies-irae2 Główny moduł programu. Nie zawiera kodu


Javy, służy do zarzadzania
˛ innymi modułami.
dies-irae:dies-assembly Kolejny moduł nie zawierajacy ˛ kodu Javy,
zawierajacy
˛ natomiast pliki służace
˛ do uruchamiania programu.
Służy on do tworzenia gotowej dystrybucji programu.
dies-irae:dies-config Moduł konfiguracyjny. Moduł ten ma za za-
danie uniezależniać wszystkie inne moduły od środowiska uru-
chomienia, na przykład pozwala konfigurować nazw˛e portu, do
którego podłaczono
˛ silniki krokowe (tak by nazwa ta nie musiała
być wkompilowana w kod programu). Zawiera też wszystkie staty-
czne obiekty.
1 Patrz np. 3.10. Moduł dies-gui-shared nie powinien zależeć od klas z

genieConnector i encore-silniki. Przy takim podziale nie ma on tych klas w swoim


classpath’u (czyli inaczej mówiac
˛ klasy z tego modułu nie widza˛ klas z genieConnector
i encore-silniki).
2 Nazwy podane tutaj sa˛ nazwami artefaktów systemu maven2 dostarczanych przez

dany moduł. Opis terminologii i działania systemu maven2 znajduje sie˛ w rozdziale 3.3.

12
dies-irae:encore-silniki Moduł odpowiedzialny za komunikacj˛e
po porcie szeregowym z silnikami krokowymi.
dies-irae:genie-connector Moduł odpowiedzialny za komunikacj˛e
z osprzetem
˛ Canberry (tory spektrometryczne).
dies-irae:encore-symulacja Moduł wyświetlajacy
˛ animowana˛ sy-
mulacje˛ eksperymentu.
dies-irae:dies-gui Moduł zawierajacy
˛ graficzny interfejs użytko-
wnika.
dies-irae:dies-peakfinder Moduł zawierajacy˛ klas˛e odpowiedzialna˛
za wyznaczanie pików w zebranych spektrach.

3.3 Opis systemu Maven


Ponieważ projekt jest budowany za pomoca˛ mavena (i budowanie go
bez użycia tego narz˛edzia byłoby ucia˛żliwe), a zarazem narz˛edzie to jest
słabo znane, postanowiono opisać jego działanie i zastosowania.
Apache Maven 2, a w skrócie maven (i tej nazwy b˛edziemy uży-
wać) jest narz˛edziem do zarzadzania
˛ projektami informatycznymi. Przy-
toczmy opis celów, jakie system ten chce osiagn ˛ ać:
˛

“Głównym celem mavena jest umożliwienie programiście


zrozumienia całego stanu projektu programistycznego w naj-
krótszym możliwym czasie. By osiagn˛ ać
˛ ten cel maven stara
radzić sobie‘ z nastepuj
˛ acymi
˛ zagadnieniami:
Ułatwienie procesu budowania projektu Mimo, iż używanie
mavena nie zwalnia programisty ze znajomości mech-
anizmów budowania projektu, to jednak zwalnia go z
dogladania
˛ detali.
Udostepnienie
˛ jednolitego systemu budowy projektów
Maven pozwala zbudować projekt używajac ˛ tylko mod-
elu obiektowego projektu3 oraz zbioru wtyczek4 , które sa˛
wspólne dla wszystkich projektów mavena, tworzac ˛ jed-
nolity system budowy aplikacji. Gdy tylko programista
zapozna si˛e z jednym projektem mavena — automaty-
cznie wie, w jaki sposób budowane sa˛ inne projekty
mavena, co oszcz˛edza mu czas poświ˛ecany na przegla- ˛
danie wielu projektów[8]5 .”

Maven potrafi kontrolować budow˛e, testowanie, zarzadzanie


˛ zależno-
ściami, dystrybucja,
˛ dokumentacja˛ projektu oraz jego wieloma innymi
aspektami[9]6 .
3 Chodzi o plik pom.xml zawierajacy
˛ wszystkie informacje potrzebne do budowy mod-
elu (przypis autora).
4 Wtyczek systemu maven (przypis autora).
5 Tłumaczenie własne.
6 Zainteresowanych odsyłam do [10].

13
Dlaczego Maven
Zdecydowano sie˛ na używanie mavena w tym projekcie głównie ze
wzgl˛edu na jego możliwości zarzadzania
˛ zależnościami7 . Gdy w katalogu
lib znajduje sie˛ wiecej
˛ niż kilka plików (bieżaco
˛ projekt ten zależy od
26 bibliotek), zarzadzanie
˛ nimi staje si˛e trudne. Ponadto, gdy zależności
maja˛ własne zależności, cały proces re˛ cznego zarzadzania
˛ nimi staje
si˛e ucia˛żliwy. Maven rozwiazuje
˛ ten problem, gdyż jest w stanie na
bieżaco
˛ pobierać prawidłowe wersje zależności. Ponadto maven jest
używany w tym projekcie do tworzenia plików dystrybucji (czyli skom-
presowanego pliku zwierajacego ˛ wszystkie pliki niezbedne
˛ do działania
programu oraz skrypty startowe).
Wreszcie program ten jest tworzony w środowisku programisty-
cznym Intellij Idea 8 , które w czasie tworzenia projektu było płatne —
a uznano, że powinno si˛e dostarczyć łatwa˛ metod˛e na prac˛e z pro-
jektem w darmowych IDE9 (wszystkie główne IDE Javy sa˛ w stanie
pracować używajac ˛ informacji z plików pom.xml; o tym jak otwierać
projekt w różnych IDE dokładniej w rozdziale 4.4).

Słownik mavena
Artefakt (z ang. artifact) Jest to bardzo ogólne określenie na produkt
końcowy budowania programu. Może być to plik JAR10 zawier-
ajacy
˛ skompilowany kod źródłowy (i właśnie w tym sensie jest
on używany w tym programie), ale może to być plik zawierajacy˛
dokumentacje projektu czy jego kod źródłowy. W Mavenie każdy
artefakt ma tak zwane współrzedne,
˛ które jednoznacznie go iden-
tyfikuja.
˛
Współrzedne
˛ artefaktu (z. ang coordinates) Sa˛ to dane, które jed-
noznacznie identyfikuja˛ dany artefakt. Maven obsługuje nast˛epu-
˛ współrz˛edne: groupId, artifactId, version oraz kilka innych
jace
(których nie używam w tym projekcie — zainteresowanych odsy-
łam do [11]).
GroupId Ciag˛ znaków unikalny na poziomie organizacji, która dany
artefakt stworzyła. Jeśli dany artefakt ma być dostepny
˛ publicznie,
groupId powinna zaczynać si˛e od odwróconego adresu domeny,
która˛ dana organizacja posiada (tak jak przyjmuje si˛e przy tworze-
niu nazw pakietów Javy).
ArtifactId Ciag
˛ odróżniajacy
˛ jeden artefakt w grupie od drugiego.
Version Wersja. Pozwala odróżnić różne wersje tego samego artefaktu.
7 Dokładniej ten termin zostanie wyjaśniony później, ale na razie przez słowo: “za-

leżność” należy rozumieć: “biblioteka”.


8 Strona domowa http://www.jetbrains.com/idea/
9 (z ang. Integrated Developer Enviorment — zintegrowane środowisko programisty-

czne. Dokładnie o tym jakie kroki należy podjać˛ by uruchomić projekt w różnych IDE w
rozdziale 4.4.
10 Java Archive, plik zawierajacy ˛ skomplikowane klasy Javy, spakowany algorytmem
ZIP.

14
Id artefaktu Wszystkie współrz˛edne artefaktu można połaczyć
˛ w jeden
ciag
˛ znaków w nast˛epujacy
˛ sposób: groupId:artifactId:ver-
sion, np: dies-irae:dies-assembly:1.0.0.
Zależność (z ang. dependency) Artefakt, którego dany projekt wy-
maga do poprawnego działania.
Zasieg
˛ zależności (z ang. scope) Zależności moga˛ mieć różne zasi˛egi,
tj. być dost˛epne w różnych momentach budowy aplikacji. Domyśl-
nie zależności maja˛ zasieg
˛ compile, co znaczy, że dost˛epne sa˛
zawsze. Zależności o zasi˛egu test nie sa˛ widoczne w gotowym
programie, ale dostepne
˛ sa˛ w fazie testów.
Repozytorium Zbiór artefaktów udost˛epniony Mavenowi (na przykład
umieszczony jako strona internetowa albo dost˛epny na dysku).
Podczas budowy projektu maven pobiera wszystkie (nie pobrane
przy poprzednich budowach) zależności z repozytoriów zdefiniowa-
nych w pliku POM.
Plik POM11 Plik zawierajacy ˛ wszystkie dane o projekcie. Podstawowe
dane, jakie plik POM może zawierać to: współrz˛edne artefaktu
jaki ten plik opisuje, zależności projektu, repozytoria, jakie należy
sprawdzać, programiści i organizacja tworzaca ˛ dany projekt, li-
cencja projektu i tak dalej. Plik pom znajduje si˛e w głównym
katalogu projektu i ma nazwe˛ pom.xml12 .
Dziedziczenie Maven udost˛epnia mechanizm dziedziczenia plików
POM. Tj. jeśli moduł B zaznaczy, że jego rodzicem jest moduł
A, to wszystkie własności modułu A b˛eda˛ własnościami modułu
B.

3.4 Moduł dies-irae:dies-irae


Moduł ten zawiera tylko plik POM zawierajacy˛ wspólne własności
wszystkich innych modułów. Pełny listing pliku pom.xml:
1 <?xml version="1.0" encoding="UTF-8"?>
2 <project >
3 <modelVersion>4.0.0</modelVersion>
4 <groupId>dies-irae</groupId>
5 <artifactId>dies-irae</artifactId>
6 <packaging>pom</packaging>
7 <version>1.0</version>
8 <modules>
9 <module>dies-lmarq</module>
10 <module>encore-silniki</module>
11 <module>encore-symulacja</module>
12 <module>dies-peakfinder</module>
13 <module>dies-assembly</module>
11 (z ang.) Project Object Model
12 Dokładny opis pliku pom.xml znajduje sie˛ w [11]

15
14 <module>dies-config</module>
15 <module>web-backend</module>
16 <module>dies-gui-shared</module>
17 <module>dies-gui-onSite</module>
18 </modules>
19 <build>
20 <pluginManagement>
21 <plugins>
22 <plugin>
23 <groupId> org.apache.maven.plugins
</groupId>
24 <artifactId> maven-compiler-plugin
</artifactId>
25 <configuration>
26 <source>1.6</source>
27 <target>1.6</target>
28 <encoding>UTF-8</encoding>
29 </configuration>
30 </plugin>
31 </plugins>
32 </pluginManagement>
33 </build>
34 <repositories>
35 <repository>
36 <id>skimble-public</id>
37 <url> http://skimbleshanks.ath.cx/maven2/ </url>
38 <!-- Publiczne repozytorium autora -->
39 </repository>
40 </repositories>
41 <dependencies>
42 <dependency>
43 <groupId>junit</groupId>
44 <artifactId>junit</artifactId>
45 <version>4.5</version>
46 <scope>test</scope>
47 </dependency>
48 <dependency>
49 <groupId>org.slf4j</groupId>
50 <artifactId>slf4j-log4j12</artifactId>
51 <version>1.5.6</version>
52 <scope>test</scope>
53 </dependency>
54 </dependencies>
55 <dependencyManagement>
56 <dependencies>
57 <dependency>
58 <groupId>org.slf4j</groupId>
59 <artifactId>slf4j-api</artifactId>
60 <version>[1.0,)</version>
61 </dependency>

16
62 <dependency>
63 <groupId>junit</groupId>
64 <artifactId>junit</artifactId>
65 <version>4.5</version>
66 <scope>test</scope>
67 </dependency>
68 <dependency>
69 <groupId>edu.umd.cs.findbugs</groupId>
70 <artifactId>annotations</artifactId>
71 <version>1.3.9</version>
72 </dependency>
73 <dependency>
74 <groupId>commons-collections</groupId>
75 <artifactId>commons-collections</artifactId>
76 <version>3.2.1</version>
77 </dependency>
78 <dependency>
79 <groupId>net.java.dev.beansbinding</groupId>
80 <artifactId>beansbinding</artifactId>
81 <version>1.2.1</version>
82 </dependency>
83 <dependency>
84 <groupId>commons-math</groupId>
85 <artifactId>commons-math</artifactId>
86 <version>1.2</version>
87 </dependency>
88 <dependency>
89 <groupId>commons-primitives</groupId>
90 <artifactId>commons-primitives</artifactId>
91 <version>1.0</version>
92 </dependency>
93 <dependency>
94 <groupId>commons-lang</groupId>
95 <artifactId>commons-lang</artifactId>
96 <version>2.4</version>
97 </dependency>
98 <dependency>
99 <groupId>jfree</groupId>
100 <artifactId>jfreechart</artifactId>
101 <version>1.0.13</version>
102 </dependency>
103 <dependency>
104 <groupId>com.miglayout</groupId>
105 <artifactId>miglayout</artifactId>
106 <version>3.7</version>
107 </dependency>
108 </dependencies>
109 </dependencyManagement>
110 </project>

17
Poziom jezyka
˛ Java Fragment pliku zaczynajacy ˛ si˛e od linii 22 po-
woduje, że maven b˛edzie kompilował kod używajac ˛ rozszerzeń jezyka
˛
z wersji 1.6 Javy, oraz że maven bedzie
˛ zakładać, że kodowanie plików
to UTF-8.

Moduły W linii 8 zaczyna si˛e sekcja definiujaca


˛ moduły projektu
dies-irae.

Ustawienie poziomu jezyka ˛ Java By ustawić poziom j˛ezyka Java


podczas kompilacji programu za pomoca˛ systemu maven, należy odpo-
wiednio skonfigurować wtyczke˛ odpowiadajac˛ a˛ za kompilacje.
˛ Konfigu-
racja ta zaczyna sie˛ w linii 22.

Konfiguracja repozytoriów W linii 35 definiuje si˛e repozytoria, które


maven b˛edzie przeszukiwać w poszukiwaniu zależności. Domyślnym re-
pozytorium (którego nie trzeba konfigurować) jest główne repozytorium
Mavena, drugim dodanym jest publiczne repozytorium autora — za-
wiera zależności, których brakowało w głównym repozytorium lub były
tam w niepełnej wersji — na przykład nie zawierały kodu źródłowego
czy nie zawierały odpowiednio opisanych zależności.

Zależności W linii 41 rozpoczynana si˛e konfiguracja zależności. Wszy-


stkie zależności tego głównego modułu bed
˛ a˛ zależnościami pozostałych
modułów. Tutaj definiujemy dwie zależności niezb˛edne do prawidłowego
działania testów: junit — najpopularniejszy framework do pisania
testów w Javie — oraz wtyczke˛ do systemu logowania.

Zarzadzanie
˛ zależnościami W linii 56 rozpoczyna si˛e zarzadzanie
˛
zależnościami; jest to funkcjonalność mavena upraszczajaca
˛ tworzenie
projektów składajacych˛ si˛e z wielu modułów. W zwykłym schemacie
uruchamiania programów w całym programie może być tylko jedna wer-
sja danej klasy, a co za tym idzie, jedna wersja danej biblioteki. Gdyby
definiować wersj˛e i zasi˛eg zależności w podmodułach głównego modułu
mogłoby si˛e okazać że jeden że poszczególne podmoduły wymagaja˛
różnych wersji danych bibliotek13 , zmiana wersji biblioteki dla całego
projektu byłaby też czasochłonna. Jeśli dana zależność jest umieszc-
zona w sekcji dependencyManagement
w projekcie rodzicu, to w projekcie dziecku starczy przy definiowaniu
owej zależności podać tylko artifactId i groupId, natomiast wersja
i zasieg
˛ zostana˛ odziedziczone od rodzica.

3.5 Moduł dies-irae:dies-assembly


Moduł ten służy do budowania gotowej dystrybucji programu.
13 Samo w sobie nie jest to złe. Jeśli różne podprojekty bed
˛ a˛ uruchamiane jako różne
aplikacje jest to poprawne rozwiazanie.
˛

18
Plik pom
Plik pom tego modułu jest bardzo prosty - mówi, iż zależnoś-
cia˛ tego modułu jest moduł dies-gui-onSite zawierajacy ˛ interfejs
graficzny (wszystkie pozostałe moduły uwzgl˛edniane sa˛ gdyż sa,
˛ zależno-
ściami dies-gui-onSite) oraz, że plik zawierajacy
˛ opis dystrybucji to
assembly.xml.
1 <?xml version="1.0" encoding="UTF-8"?>
2 <project>
3 <parent>
4 <artifactId>dies-irae</artifactId>
5 <groupId>dies-irae</groupId>
6 <version>1.0</version>
7 </parent>
8 <modelVersion>4.0.0</modelVersion>
9 <artifactId>dies-assembly</artifactId>
10 <build>
11 <plugins>
12 <plugin>
13 <artifactId> maven-assembly-plugin
</artifactId>
14 <configuration>
15 <descriptors>
16 <descriptor>
17 assembly.xml
18 </descriptor>
19 </descriptors>
20 </configuration>
21 </plugin>
22 </plugins>
23 </build>
24 <dependencies>
25 <dependency>
26 <groupId>dies-irae</groupId>
27 <artifactId>dies-gui-onSite</artifactId>
28 <version>1.0</version>
29 </dependency>
30 <dependency>
31 <groupId>org.slf4j</groupId>
32 <artifactId>slf4j-log4j12</artifactId>
33 <version>1.5.6</version>
34 </dependency>
35 </dependencies>
36 </project>

Plik assembly
Plik tworzy archiwa dystrybucyjne. Opis dystrybucji programu w
punkcie 4.

19
1 <assembly>
2 <id>dependencies</id>
3 <formats>
4 <format>zip</format>
5 </formats>
6 <includeBaseDirectory>false</includeBaseDirectory>
7 <fileSets>
8 <fileSet>
9 <directory>target</directory>
10 <includes><include>*.jar</include></includes>
11 <outputDirectory>/lib</outputDirectory>
12 </fileSet>
13 <fileSet>
14 <directory>native/</directory>
15 <outputDirectory>lib/native</outputDirectory>
16 <includes>
17 <include>**</include>
18 </includes>
19 </fileSet>
20 <fileSet>
21 <directory>bin</directory>
22 <outputDirectory>/</outputDirectory>
23 <includes>
24 <include>*.sh</include>
25 <include>*.bat</include>
26 <include>*.exe</include>
27 </includes>
28 <fileMode>0755</fileMode>
29 </fileSet>
30 </fileSets>
31 <dependencySets>
32 <dependencySet>
33 <outputDirectory>/lib</outputDirectory>
34 <unpack>false</unpack>
35 <scope>runtime</scope>
36 </dependencySet>
37 </dependencySets>
38 </assembly>

3.6 Moduł dies-irae:dies-config


Moduł ten zawiera konfiguracj˛e współdzielona˛ przez wszystkie inne
moduły. Z poziomu Javy konfiguracja jest enkapsulowana14 w instancji
klasy ConfigurationBean, dostepnej
˛ poprzez wywołanie metody Con-
figuration.getConfiguration().
Pliki konfiguracyjne ładowane sa˛ przy użyciu klasy java.util.
Properties. Wartości domyślne konfiguracji sa˛ elementem pliku jar
14 Enkapsulacja jest pojeciem
˛ oznaczajacym
˛ ukrywanie pewnych detali implementacji
przed klientami danego konstruktu programistycznego.

20
zawierajacego
˛ ten moduł i znajduja˛ si˛e w pliku o nazwie default.
properties, wartości dost˛epne dla użytkownika dla konfiguracji po-
szukiwane sa˛ w katalogu .config w katalogu głównym programu
i maja˛ nazwe˛ dies-irae.properties.
Przykładowy plik konfiguracyjny:
1 # Nazwy detektorow
2 gammaDetecorLocator = DET_2
3 electronDetectorLocator = DET_1
4 #Ilosci kanalow w analizatorze
5 electonChannelCount = 1024
6 gammaChannelCount = 1024
7 #Paramery domyslnej prostej kalibracji y[KeV]=a*numer
kanalu +
8 #Zbadane empirycznie, orientacyjne
9 defaultBetaCalibration.a = 1.5261
10 defaultBetaCalibration.b = -36.1333
11 defaultGammaCalibration.a = 1.4658
12 defaultGammaCalibration.b = -24.8306
13 #Czy uzywac domyslnej kaibracji detektorow
14 calibrated = false
15 #Port COMM pod ktorym jest silnik
16 driverPort = COM9
17 #Domyslna kalibracjia silnikow - zbadana empirycznie
18 defaulrDriverCalibration.a = -0.3307
19 defaulrDriverCalibration.b = 107

Konfiguracja kalibracji detektorów


Kalibracja detektorów również jest konfigurowalna. Można wprowa-
dzić do programu prekonfigurowane linie które posłuża˛ do kalibracji
detektora. Z poziomu Javy linie te sa˛ enkapsulowane w instancji klasy
CalibrationBean dost˛epnej poprzez wywołanie CalibrationProper-
ties.getProperties().
Wartości domyślne konfiguracji sa˛ elementem pliku jar zawie-
rajacego
˛ ten moduł i znajduja˛ si˛e w pliku o nazwie calibration.
properties, wartości dost˛epne dla użytkownika dla konfiguracji po-
szukiwane sa˛ w katalogu .config w katalogu głównym programu
i maja˛ nazwe˛ calibration.properties.
Przykładowy plik konfiguracyjny:
line.name=Cs;Co1;Co2;Eu1;Eu2;Eu3;Eu4
line.energy=660;1170;1332;122;245;344;791

3.7 Moduł dies-irae:encore-silniki


Moduł ten zajmuje si˛e komunikacja˛ programu z silnikami kroko-
wymi. Komunikacja odbywa si˛e za pośrednictwem sprz˛etowego ste-
rownika. Komunikacja ze sterownikiem odbywa sie˛ za pośrednictwem
portu RS 232.

21
Sterownik udostepnia
˛ trzy polecenia o nastepuj
˛ acym
˛ formacie:

Liczba15 Nakazuje wykonać silnikowi N kroków z bieżac


˛ a˛ predkości
˛ a˛
!Liczba Ustawia predkość
˛ obrotu silnika
? Zwraca bieżace
˛ położenie jako liczbe˛ od 0 do 1023.
Każdorazowo przed wykonaniem polecenia wydajacego ˛ rozkaz obrotu
należy ustawić predkość,
˛ tj. należy zawsze wysyłać sekwencje:
˛
!predkosc\rodleglosc\r

Założenia modułu
Moduł musi udostepniać
˛ nastepuj
˛ ace
˛ operacje:

Obrót detektora do ustalonego kata ˛ Ponieważ obrót jest operacja, ˛


która trwa długo (ponad sekunde),
˛ należy umożliwić wykonanie tej
operacji na dwa sposoby: blokujac˛ wykonanie bieżacego
˛ watku
˛ do
czasu dojechania na miejsce oraz, asynchronicznie — opuszczenie
metody nakazujacej˛ obrót po zadaniu rozkazu obrotu (z udo-
st˛epnieniem mechanizmu notyfikacji o zakończeniu obrotu i o
przerwaniu go z jakichś przyczyn). Patrz 3.7.
Obrót w określonym kierunku i zatrzymanie Używane do re˛ cznej
manipulacji położeniem tarczy.

Moduł powinien być skonstruowany tak, żeby silniki si˛e wyłaczały


˛
przy zerwaniu kontaktu z komputerem.

Komunikacja z portem szeregowym


Java SE nie udost˛epnia narz˛edzi umożliwiajacych
˛ połaczenie
˛ sie˛ za
pomoca˛ portu szeregowego, do komunikacji z portem szeregowym służy
rozszerzenie Javy o nazwie Java Communications API16 . Niestety Sun
nie udostepnia
˛ implementacji tego API dla systemu operacyjnego Win-
dows. Implementacja jest dostepna˛ ˛ projektowi RXTX17 .
dzieki
Jedyna˛ różnica˛ mi˛edzy RXTX a Java Communications API jest to,
że klasy RXTX znajduja˛ si˛e w pakiecie gnu.io, podczas gdy SUN swoje
klasy umieścił w javax.comm.
15 Dokładniej format polecenia to: Liczba\r. Wszystkie polecenia powinny sie ˛
kończyć sekwencja˛ \r.
16 Strona projektu http://java.sun.com/products/javacomm/ dostep
˛ z dnia 21-09-
09.
17 Strona główna http://rxtx.qbang.org, dostep˛ z dnia 21-09-2009

22
Rysunek 3.1: Schemat UML klasy EngineDriver

Wymagania modułu
Moduł ten wymaga, by w katalogu Windows\\System3218 umieścić
natywne biblioteki RXTX19 . Z pobranych archiwów należy wyodre˛ bnić
plik rxtxSerial.dll i umieścić go w wzmiankowanym wyżej katalogu.

Schemat modułu
Moduł ten składa si˛e z trzech głównych klas, które posiadaja˛
nastepuj
˛ ace
˛ obszary odpowiedzialności:

EngineDriver Klasa ta enkapsuluje port. Kiedy tworzono ten ten frag-


ment aplikacji, autor nie był pewien, czy RXTX jest dostatecznie
stabilna, by obsługiwać ten program. Klasa ta enkapsuluje RXTX
— zapewniała ona, że zmiana tej biblioteki na dowolna˛ inna˛ nie
spowoduje zmian poza ta˛ klasa. ˛ Schemat UML20 tej klasy znajduje
sie˛ na rys. 3.1. Klasa ta udostepnia
˛ strumienie wejścia portu jako
instancj˛e InputStream oraz strumień wyjścia portu za pośred-
nictwem metody writeToOutput(byte[]), która oprócz wysłania
danych (w zależności od konfiguracji logowania) zapisuje je do
loga.
CommandDriver Klasa ta enkapsuluje sprzetowy
˛ driver silników i umoż-
liwia wysyłanie rozkazów jako obiektów Java, pozwala też odbierać
informacje zwrotne od drivera.
PositionDriver Klasa pozwalajaca
˛ na obrót silnika do określonej
pozycji.
CalibratedDriver Klasa pozwalajaca
˛ na obrót silnika do określonego
kata.
˛

18 Albo w innym katalogu, w którym wywołanie System.loadLibrary bedzie


˛ poszuki-
wać bibliotek.
19 Sa˛ one dostepne
˛ ze stronty RXTX pod adresem http://rxtx.qbang.org/pub/
rxtx/rxtx-2.1-7-bins-r2.zip., oraz na serwerze Autora http://jbzdak.ath.cx/
inz/rxtx-2.1-7-bins-r2.zip.
20 Unified Moddeling Language — wystandaryzowany jezyk
˛ modelowania w dziedzinie
inżynierii oprogramowania.

23
Rysunek 3.2: Schemat UML klasy CommandDriver

Klasa CommandDriver
Klasa ta enkapsuluje podstawowa˛ komunikacj˛e z driverem silników.
Jej główna˛ odpowiedzialnościa˛ jest:

Wysyłanie rozkazów Metoda executeCommand(CommandObject) wy-


konuje rozkaz i odbiera odpowiedź. Metoda ta blokuje wykonanie
bieżacego
˛ watku
˛ na czas wysłania rozkazu i przetworzenia odpo-
wiedzi. Uwaga: watek
˛ jest blokowany do czasu wysyłania rozkazu
— a nie do końca wykonywania rozkazu przez silniki.
Synchronizacja Klasa ta udostepnia
˛ synchronizacje danych oraz
umożliwia dostep
˛ do jej instancji z wielu watków.
˛

Schemat klas CommandObject (enkapsulujacej


˛ rozkaz) i Command-
Driver znajduje sie˛ na rys 3.2.

Klasa PositionDriver
Klasa ta pracuje na współrz˛ednych zwiazanych
˛ z pozycja,
˛ czyli liczba˛
zwracana˛ przez rozkaz ?. Pozwala wykonać nastepuj
˛ ace
˛ operacje:

Obrót do ustalonej pozycji Operacj˛e t˛e można wykonać na dwa spo-


soby — synchronicznie (watek
˛ wykonujacy˛ t˛e operacj˛e jest blo-
kowany aż do jej zakończenia) lub asynchronicznie — (metoda

24
kończy si˛e natychmiast po wydaniu silnikom rozkazu, opcjonalny
parametr DriverCallback pozwala na otrzymanie notyfikacji po
zakończeniu wykonywania rozkazu.
Algorytm działania tej metody jest nastepuj
˛ acy:
˛
• Wykonywany jest pomiar położenia.
• Wyznaczana jest różnica położeń, znajac˛ ja˛ oblicza si˛e pre˛ d-
kość obrotu silników oraz ilość kroków do wykonania w ten
sposób, by silniki kre˛ ciły si˛e do nast˛epnego sprawdzenia
położenia (ale nie wiele dłużej). W ten sposób silniki kre˛ ca˛
si˛e jednostajnie, a po zerwaniu kontaktu z komputerem
samoczynnie staja. ˛
• Przez 50 ms czekamy do nastepnego
˛ pomiaru położenia.
Obrót w określonym kierunku aż do otrzymania polecenia zatrzyma-
nia sie.
˛
Algorytm działania jest analogiczny jak w przypadku obrotu do
ustalonej pozycji, z tym że pre˛ dkość i ilość kroków ustalone sa˛ na
sztywno.
Zatrzymanie Zatrzymuje silniki

Pozostałe własności i zależności umieszczono na diagramie 3.3.


Własności oznaczone «bound» sa˛ bound properties w rozumieniu spe-
cyfikacji Java Beans — czyli ich zmiana spowoduje notyfikacj˛e zare-
jestrowanych w danej instancji PositionDrivera PropertyChange-
Listener’ów[12, punkt 74.1]. Opis pozostałych niestandardowych oz-
naczeń z diagramów UML znajduje sie˛ w punkcie: 5.3.

Klasa CalibratedDriver Dziedziczy po PositionDriver. Pozwala


na przeliczanie pozycji na katy.
˛ Własności tej klasy znajduja˛ si˛e na
diagramie: 3.4.

3.8 Moduł genie-connector


Moduł ten zawiera klasy łacz ˛ ace
˛ si˛e z oprogramowaniem Genie 2000
v. 3.2 dostarczanym przez Canberre˛ — producenta wszystkich ele-
mentów toru spektrometrycznego. Założeniem projektowym było tutaj
maksymalne uproszczenie pracy z biblioteka˛ Canberry — udost˛epnie-
nie tej biblioteki za pośrednictwem API21 chroniacego ˛ użytkownika
biblioteki przed jej złożonościa.
˛

Oprogramowanie Canberry
Najpierw oddajmy głos producentowi.

“Oprogramowanie Genie 2000 jest oparte o paradygmat


rozdziału na klient i serwer. Ta architektura pozwala na
21 Aplication Interface — interfejs programistyczny.

25
Rysunek 3.3: Klasa PositionDriver

Rysunek 3.4: Klasa CalibratedDriver

26
podzielenie aplikacji na dwa komponenty — klient i serwer,
które moga˛ zarówno być wykonywane na jednym komputerze,
jak i być rozproszonymi miedzy
˛ komputerami połaczonymi
˛
siecia.
˛ Podsystem IPC (InterProcess Communicaton — ko-
munikacja mi˛edzy procesami), dostarcza warstwe˛ łacz
˛ ac
˛ a˛ te
komponenty.
Komponent pełniacy ˛ role˛ serwera (zwany VDM — Virtual
Data Manager) udostepnia
˛ usługi spektroskopowe. Interfejs
tych usług, które zawieraja˛ miedzy
˛ innymi odczyt danych
zapisanych na dysku i dost˛ep do elektronicznych urzadze
˛ ń
pomiarowych jest z punktu widzenia aplikacji klienckich
spójnym generycznym API”[13, s. 23]22 .
Oprogramowanie Canberry udost˛epnia interfejs napisany w C z
którego zdecydowałem sie˛ skorzystać.

Słownik terminów Canberry


Krótkie wyjaśnienie terminów, zaczerpnietych
˛ z dokumentacji Can-
berry, którymi bed
˛ e˛ sie˛ posługiwać:

VDM Virtual Data Manager komponent pełniacy


˛ role˛ serwera i udost˛e-
pniajacy
˛ dane klientom.
DSC Data Source Context referencja, która przechowuje dane o źródle
danych. Zgodnie z dokumentacja˛ programista nie ma dostepu ˛ do
jej pól, wszystkie operacje na niej należy wykonywać za pomoca˛
funkcji dostarczonych przez Canberre. ˛
SAD System Access to Data tak określa si˛e wszystkie metody udost˛ep-
niajace
˛ dane z DSC.

Wymagania biblioteki Do prawidłowego działania jakiejkolwiek fun-


kcji wymagane jest uprzednie wywołanie:
void vG2KEnv();
która odczytuje z rejestru dane konfiguracyjne oprogramowania. Fun-
kcja ta jest wywoływana w statycznym bloku inicjalizacji klasy Ge-
nieConnectorStaticData (patrz punkt 3.8, linia 11).

Parametry
Jedna˛ z zasadniczych funkcjonalności biblioteki Canberry jest umoż-
liwienie zapisu i odczytu parametrów. Do odczytu i zapisu parametrów
służa˛ odpowiednio funkcje SadGetParam i SadPutParam, funkcje te
maja˛ taka˛ sama˛ sygnature:
˛
SADENTRY SadGetParam(HMEM hDSC, ULONG ulParam,
USHORT usRecord, USHORT usEntry, void *
pvData, USHORT usExpect );
22 Tłumaczenie własne

27
Wyjaśnienie znaczenia parametrów:
hDSC DSC, z którego pobieramy parametr
ulParam Numer parametru
usRecord Numer rekordu w parametrze.
usEntry Numer entry w parametrze23 .
pvData Zaalokowany obszar, w którym znajduje si˛e wartość parametru
do zapisania (podczas zapisu) lub który bedzie
˛ zawierać wartość
zapisana˛ (podczas odczytu).
usExpect Długość pvData w bajtach.

Łaczenie
˛ Javy i C
Standardowo do komunikacji z kodem C korzysta si˛e z mechanizmu
JNI24 bed
˛ acego
˛ elementem standardowej dystrybucji Javy. Rozważmy
jednak najpierw, jak działa JNI. Przykładowo by stworzyć natywna˛
metode˛ o nastepuj
˛ acej
˛ sygnaturze:
package pkg;

class Cls {
native double f(int i, String s);
}
należy stworzyć nastepuj
˛ ˛ kod w C25 :
acy
1 jdouble Java_pkg_Cls_f__ILjava_lang_String_2 (
2 JNIEnv *env, /* interface pointer */
3 jobject obj, /* "this" pointer */
4 jint i, /* argument #1 */
5 jstring s /* argument #2 */ ){
6 /* Obtain a C-copy of the Java string */
7 const char *str = ( *env)->GetStringUTFChars(env,
s, 0);
8 /* process the string */
9 ...
10 /* Now we are done with str */
11 ( *env)->ReleaseStringUTFChars(env, s, str);
12 return ...
13 }
Jak widzimy JNI jest mechanizmem skomplikowanym, zdecydowano
˛ na użycie biblioteki JNA (Java Native Access)26 . Oddajmy głos
si˛e wiec
autorom:
23 Dokumentacja biblioteki jest bardzo enigmatyczna jeśli chodzi o znaczenie
parametrów usEntry i usRecord. Patrz [13] strony: 41 — 43. Domyślnie jest to albo
0 albo 1. Dokumentacja wskazuje że powinno być to 1 ([13] str 42), poza tak zwanymi
Common parameters dla których jest to 0 ([13] str. 71)
24 Java Native Interface
25 Przykłady pochodza˛ z [14]
26 Główna strona projektu https://jna.dev.java.net/

28
“JNA udost˛epnia programom Javy łatwy dost˛ep do naty-
wnych współdzielonych bibliotek (dla Windows bibliotek
DLL27 ) piszac
˛ tylko kod Javy”[15].
JNA ma dwie zasadnicze wady:
Wymaga dostepu˛ do bibliotek DLL JNA wymaga, by kod, do którego
łaczy
˛ si˛e program, był dost˛epny jako biblioteka DLL28 . Canberra
nie dostarczyła biblioteki DLL, implementacja API Canberry jest
dost˛epna poprzez statyczna˛ bibliotek˛e. Autorowi nie udało si˛e
znaleźć bezpłatnych narz˛edzi konwertujacych
˛ biblioteki statyczne
na biblioteki DLL. Stworzono wiec ˛ program który wygenerował z
plików nagłówkowych nagłówek biblioteki DLL (patrz rozdział 5.3).
JNA jest powolna29 Celem projektowym JNA nie jest szybkość wyko-
nania kodu, lecz łatwość jego tworzenia. Jednak problem tego, że
JNA jest wolniejsze, nie jest istotny w tej aplikacji — kod natywny
jest wywoływany na tyle rzadko że wszelkie narzuty generowane
przez JNA sa˛ nieistotne.
Drugim rozwiazaniem
˛ problemu pre˛ dkości mogłoby być użycie tzw.
direct mapping. Jest to specjalna metoda mapowania korzystajaca ˛
z JNA, która jednak ma wydajność porównywalna˛ z JNI[15]. Byłby
on używany od poczatku,
˛ został dodany do JNA już gdy projekt
genieConnetcor był znacznie zaawansowany.

Opis biblioteki JNA


Filozofia działania JNA jest nast˛epujaca:
˛ programista tworzy spe-
cjalny interfejs, który zawiera deklaracje funkcji odpowiadajacych
˛ fun-
kcjom w danej bibliotece DLL, nast˛epnie JNA dostarcza implementacj˛e
tego interfejsu wywołania, która wykonuje odpowienie wywołania fun-
kcji DLL. By pozyskać implementacj˛e iterfejsu, należy wywołać metod˛e
com.sun.jna.Native.loadLibrary. Posłużmy si˛e przykładem z mo-
dułu:
1 class GenieConnectorStaticData {
2
3 static final String DLL_FILENAME =
"cxAthJbzdakGenieConnector";
4
5 static final String FUNCTION_PREFIX = "DLL_WRAPPER_";
6
7 static final GenieLibrary GENIE_LIBRARY;
8 static {
9 GENIE_LIBRARY = (GenieLibrary)
10 Native.loadLibrary( DLL_FILENAME,
GenieLibrary.class,
createLibOptions());
27 (zang.) Dynamic-link library
28 Dokładniej jako bibliotek dzielna (z ang. shared library)
29 Dokumentacja biblioteki mówi, że narzut zwiazany
˛ z wywołaniem funkcji jest o rzad
˛
wielkości wiekszy,
˛ niż w przypadku JNI.

29
11 Native.setProtected(true);
12 GENIE_LIBRARY.vG2KEnv();
13 }
14
15 private static Map<String, Object>
createLibOptions() {
16 Map<String, Object> result = new HashMap<String,
Object>();
17 result.put( Library.OPTION_FUNCTION_MAPPER, new
GenieFunctionMapper());
18 return result;
19 }
20 }
W linii 10 otrzymujemy implementacj˛e interfejsu GenieLibrary,
parametry funkcji loadLibrary to: nazwa pliku dll30 , który ładu-
jemy, klasa, której implementacje˛ otrzymujemy oraz dodatkowe opcje
mapowania (o tym ostatnim później).

Mapowanie funkcji bezargumentowych


By odwzorować funkcje˛ C:
void vG2KEnv( void );
należy po stronie Javy napisać:
public void vG2KEnv();
Kiedy funkcja nie ma argumentów należy poprawnie odwzorować
tylko jej nazw˛e. Zazwyczaj nie jest to trywialne, ponieważ nowoczesne
kompilatory (szczególnie kompilatory C++) używaja˛ tak zwanego deko-
rowania nazw31 i jeśli dostarczona biblioteka jest skompilowana z włac-
˛
zona˛ opcja˛ dekorowania nazw, należy skonfigurować JNA by ta wyszuki-
wała udekorowane nazwy w pliku dll. Normalnie do tego celu służy
przekazana jako parametr wywołania loadLibrary instancja Func-
tionMapper.
W przypadku modułu genie-connector, ponieważ wyłaczono ˛ wszel-
kie dekorowanie nazw, stworzony w linii 17 FunctionMapper służy do
omijania prefiksów do funkcji. W stworzonym na potrzeby programu
pliku DLL, wszystkie funkcjie otrzymały prefix DLL_WRAPPER_. Tak
zdefiniowany function mapper b˛edzie automatycznie ów prefix dodawać.

Odwzorowywanie typów prymitywnych


Typy prymitywne (i ich obiektowe odopowiedniki) mapowane sa˛
automatycznie32 :
30 JNA bedzie
˛ poszukiwało biblioteki dokładnie w ten sam sposób co, znane z JNI,
wywołanie System.loadLibrary. Można też konfigurować metode˛ poszukiwania bib-
liotek.
31 z ang. name mangling. Wiecej˛ o dekorowaniu nazw w rozdziale o generowaniu
plików dll ze statycznych bibliotek — patrz punkt 5.3
32 Dokładna lista odwzorowań automatycznch, na stronie https://jna.dev.java.

net/javadoc/overview-summary.html#marshalling, dostep ˛ 21-09-2009

30
short SadControlDSC(unsigned short, unsigned
short);
należy stworzyć funkcje˛ o nastepuj
˛ acej
˛ sygnaturze:
public short SadControlDSC(short usDevice, short
usOpCode);

Odwzorowywanie wskaźników
Odwzorowywanie wskaźników jest skomplikowane, ponieważ praw-
idłowe ich odwzorowanie zależy od intencji autora biblioteki. Przykła-
dowo funkcja:
void doStuff(int* param);
może oczekiwać że param bedzie:
˛
• Zainicjowanym wskaźnikiem na int, tak by wynik jej działania
mógł być zwrócony przez ten wskaźnik. Wtedy poprawnym jej
odwzorowaniem jest:
void doStuff(IntByReference param);

• Zainicjalizowana˛ tablica˛ intów, wtedy poprawnym odwzorowaniem


bedzie:
˛
void doStuff(int[] param);

Co wi˛ecej, przy przenoszeniu tablic mi˛edzy kodem Javy a kodem


natywnym należy zwracać uwag˛e na problem własności pami˛eci —
cała pami˛eć automatycznie allokowana przez JNA jest zwalniana po
zakończeniu wywołania funkcji, tj. pami˛eć wskazywana przez wartość
param bedzie
˛ zwolniona zaraz po wyjściu z funkcji.
Jeśli kod natywny zachowuje referencje do pami˛eci przekazanej jako
parametr, należy używać w odwzorowaniu klasy Memory33 .
void doStuff(Memory param);

Wielokrotne odwzorowywanie funkcji


JNA zezwala na przeładowywanie nazw funkcji odwzorowujacyh ˛
dana˛ metod˛e C, tj. można w różny sposób odwzorowywać t˛e sama˛
˛ parametr z DSC34 :
metod˛e. Posłużmy si˛e przykładem funkcji pobierajacej
SADENTRY SadGetParam(ULONG ulParam, void *
pvData);
znaczenie parametrów wyjaśnione w sekcji 3.8.
Funkcje˛ te˛ można odwzorować nastepuj
˛ aco:
˛
33 Zaznaczam. W module genie-connector ta funkcjonalność nie była potrzebna.
34 Dla czytelności usunałem
˛ nieistotne argumenty funkcji

31
public short SadGetParam(NativeLong ulParam,
byte[] result);
albo nastepuj
˛ aco:
˛
public short SadGetParam(NativeLong ulParam,
NativeLongByReference result);
W pierwszym przypadku bezpośrednio odwzorowujemy void* na
byte[]. Podejście to ma jedna˛ zasadnicza˛ wad˛e — należy potem re˛ cznie
przetworzyć byte[] na docelowy typ, co po pierwsze jest jednak kodem
który trzeba napisać (a należy unikać pisania zb˛ednego kodu), po drugie
cz˛esto jest nie trywialne (a pewno nieprzenośne)35 . W drugim wypadku
odwzorowujemy void* na typ NativeLongByReference, który jest
po prostu wskaźnikiem na NativeLong. W tym wypadku mapowania
pami˛eci do typu Javy long wykonuje JNA, które bierze poprawk˛e na
różne architektury.
Można umieścić te dwa mapowania w jednym interfejsie opisujacym ˛
biblioteke˛ (i tak zreszta˛ postapiono
˛ w bibliotece genie-connector).

Odwzorowanie DSC
Wreszcie, jeśli po stronie Javy nie zamierzamy operować na wska-
źniku, możemy go odwzorować jako typ com.sun.jna.Pointer. Taka
sytuacja zachodzi w module genie-connector. Wszystkie funkcje od-
czytujace
˛ lub zapisujace ˛ dane do źródła pobieraja˛ jako pierwszy argu-
ment wskaźnik do struktury (nazwanej DSC), b˛edacej ˛ źródłem danych.
Klient biblioteki Genie nie powinien na własna˛ re˛ k˛e nic z owa˛ struktura˛
robić.
Strukture˛ te˛ pozyskuje sie˛ wyołujac
˛ funkcje˛
int iUtlCreateFileDSC( void** phDSC, BOOL
fAdvise, HWND hAdvise );
która w kodzie javy jest odwzorowana jako:
public int iUtlCreateFileDSC(PointerByReference
hDSC, int zero, int zero2);36
pierwszy argument, po wywołaniu funkcji, b˛edzie zawierać zainicjo-
wana strukture˛ hDsc.
Wszystkie pozostałe funkcje jako pierwszy argument pobieraja˛ wska-
źnik do tej struktury.
By zachować po stronie Javy bezpieczeństwo typów, można tworzyć
własne typy wskaźnikowe. Nie maja˛ one żadnej dodatkowej funkcjonal-
ności, a tylko zapewniaja˛ ochron˛e przed bł˛edami programistycznymi.
Po stronie Javy wskaźnik na hDsc b˛edzie odwzorowywany poprzez typ:
1 package cx.jbzdak.diesIrae.genieConnector;
2
3 import com.sun.jna.Pointer;

35 Przy przejściu na system 64 bitowy zmieniaja˛ sie˛ długości zmiennych.


36 Wynik tej funkcji wskazuje wystapienie
˛ (lub nie błedu),
˛ parametry zero i zero2
zgodnie z dokumentacja, ˛ musza˛ mieć wartość 0.

32
4 import com.sun.jna.PointerType;
5
6 public class DscPointer extends PointerType{
7
8 public DscPointer() {
9 super();
10 }
11
12 public DscPointer(Pointer p) {
13 super(p);
14 }
15 }

Opis modułu
Założenia modułu
JNA dostarcza tylko mapowanie funkcji C, by natomiast otrzymać
kod w pełni zgodny z paradygmatami Javy, należało dodać dodatkowe
warstwy pośrednie mi˛edzy pozostałymi modułami projektu, a intefejsem
dostarczonym przez JNA. Pozostałe moduły programu powinny widzieć
interfejs posiadajacy
˛ nastepuj
˛ ace
˛ cechy:

• Używajacy
˛ mechanizmu wyjatków
˛ do obsługi błedów.
˛
• Używajacy
˛ typów enumeracyjnych zamiast flag
• Zgodny ze specyfikacja˛ Java Beans
• Obiektowo orientowany

By spełnić powyższe założenia (i zachować rozsadn


˛ a˛ złożoność kodu)
Autor musiał rozbić odwzorowanie na cztery klasy:
GenieLibrary Klasa dokonujaca
˛ odwzorowania biblioteki Canberry.
LibraryWrapper Statyczna klasa odwzorowujaca ˛ argumenty napisane
zgodnie ze standardami Javy na zgodne z API dostarczonym przez
Canberre.
˛ Klasa ta dostarcza też obsługe˛ wyjatków.
˛
SimpleConnector Klasa która enkapsuluje DSC. Ponadto jej założe-
niem projektowym było to, żeby nie przetrzymywała żadnego stanu,
który da si˛e łatwo pobrać z DSC oraz nie odpytywała DSC pod
katem
˛ zmiany stanu.
GenieConnector Dziedziczy po SimpleConnector’ze. Ta klasa już
przetrzymuje stan z DSC, oraz periodycznie odczytuje ów stan z
DSC.

Główne różnice miedzy


˛ SimpleConnector a GenieConnector
• Każde wywołanie funkcji, która zwraca dane z DSC dla Simple-
Connector’a powoduje wywołanie funkcji SAD, podczas gdy Ge-
nieConnector zapamietuje
˛ te dane.

33
• GenieConnector co jakiś czas (domyślnie 1 sekunda) pobiera
stan z DSC.
• SimpleConnector nie jest świadom zmian jakie zachodza˛ w DSC
(przykładem takiej zmiany jest zakończenie pomiaru), podczas gdy
GenieConnector sprawdza te dane i jeśli zajda˛ zmiany wywołuje
odpowiedni PropertyChangeEvent.

Pełne mapowania
Zawartość klasy GenieLibrary:
1 package cx.jbzdak.diesIrae.genieConnector;
2
3 import com.sun.jna.Library;
4 import com.sun.jna.NativeLong;
5 import com.sun.jna.Pointer;
6 import com.sun.jna.ptr.NativeLongByReference;
7 import com.sun.jna.ptr.PointerByReference;
8 import com.sun.jna.ptr.ShortByReference;
9 import
cx.jbzdak.diesIrae.genieConnector.structs.DSQuery;
10
11 interface GenieLibrary extends Library {
12
13 public void vG2KEnv();
14
15 public int iUtlCreateFileDSC(PointerByReference hDSC,
int zero, int zero2);
16
17 public int iUtlCreateFileDSC2(PointerByReference
hDSC, int zero, int zero2);
18
19 public short SadGetStatus(DscPointer dscPointer,
NativeLongByReference result, ShortByReference
dummy1, ShortByReference dummy2);
20
21 public short SadOpenDataSource(DscPointer dsc, String
sourceName, short type, short acces, short
verify, String shellId);
22
23 public short SadGetParam(DscPointer hDSC, NativeLong
ulParam, short usRecord, short usEntry, byte[]
result, short usExpect);
24
25 public short SadGetParam(DscPointer hDSC, NativeLong
ulParam, short usRecord, short usEntry,
NativeLongByReference result, short usExpect);
26
27 public short SadPutParam(DscPointer hDSC, NativeLong
ulParam, short usRecord, short usEntry, byte[]

34
result, short usExpect);
28
29 public short SadPutParam(DscPointer hDSC, NativeLong
ulParam, short usRecord, short usEntry,
NativeLongByReference result, short usExpect);
30
31 public short SadCloseDataSource(DscPointer dsc);
32
33 public short SadDeleteDSC(DscPointer dsc);
34
35 public short SadPutStruct(DscPointer sdc, short
structType, short record, short entry, Pointer
ptr, short structSize);
36
37 public short SadFlush(DscPointer dsc);
38
39 public short SadControlDSC(DscPointer dsc, short
usDevice, short usOpCode);
40
41 public short SadGetSpectrum(DscPointer dsc, short
start, short count, short useFloats, int[]
result);
42
43 public short SadPutSpectrum(DscPointer dsc, short
start, short count, int[] input);
44
45 public short SadQueryDataSource(DscPointer
dscPointer, short opCode, DSQuery result);
46 }

Opis klasy SimpleConnector


Jej własności sa˛ opisane na diagramie numer 3.5, jej diagram
stanów znajduje si˛e na rysunku 3.6. Diagram klas, które zawieraja˛
wyniki pomiarów spektromatycznych, znajduje sie˛ na rys 3.7.

Stany klasy SimpleConnector Jak wynika z diagramu stanów (rys.


3.6) klasa ta ma bardzo prosta˛ przestrzeń stanów, na przykład nie mo-
żna powtórnie otworzyć zamknietej
˛ instancji tej klasy, to ograniczenie
wynika z założenia odwzorowania działania biblioteki Genie — DSC
również nie da sie˛ powtórnie otworzyć.
Nastepuj
˛ ace
˛ metody zmieniaja˛ stan SimpleConnectora:
void openFile(File file, Set<OpenModes> modes)
Metoda ta musi zostać wywołana, gdy instancja jest w stanie
NOT_OPENED, a jej prawidłowe wykonanie przenosi obiekt do stanu
OPEN. Funkcja ta powoduje, że dana instancja b˛edzie czerpać dane
z pliku wskazywanego przez file, który zostanie otwarty w trybie
bed
˛ acym
˛ koniunkcja˛ trybów zawartych w modes.

35
Rysunek 3.5: Schemat UML klasy SimpleConnector

Rysunek 3.6: Schemat stanów klasy SimpleConnector

36
Rysunek 3.7: Schemat stanów klas zawierajacych
˛ wyniki pomiarów
spektrometrycznych

void openSource (String datasource, Set<OpenMode> mode,


SourceType type) Funkcja ta działa analogicznie do open-
Source. Łańcuch datasource wskazuje na źródło danych, so-
urceType natomiast wskazuje na typ źródła danych.
void close() Metoda ta musi zostać wywołana, gdy instancja jest
w stanie OPEN, a jej prawidłowe wykonanie przenosi obiekt do
stanu CLOSED. Po jej wywołaniu dana nie należy wywoływać ja-
kichkolwiek innych funkcji na danej instancji omawianej klasy.

Pobieranie zebranych danych spektrometrycznych


Do pobierania danych spektrometrycznych służy funkcja:
public SpectrometricResult getSpectrometricData();
by pobrać zwartość pojedynczego kanału należy wywołać na instancji
Spectrometric Result metode: ˛
public int getCountForChannel(int channelNum);

Praca z parametrami
Biblioteka w pewnym stopniu ułatwia prac˛e z parametrami (co do
dalszych ułatwień patrz 3.8). W klasie SimpleConnector zdefiniowano
metody służace
˛ do pracy z parametrami:
public <T> T getParam(final Parameter<T> parameter,
final int record, final int entry)

public <T> void setParam(final Parameter<T>


parameter, final T value, final int record, final
int entry)

37
Interfejs parameter jest typem sparametryzowanym, parametr T to
typ parametru po stronie Javy. Ma on nastepuj
˛ ac
˛ a˛ definicje:
˛
1 public interface Parameter<T> {
2 @NonNull ParameterType<T> getType();
3
4 long getParamId();
5
6 String getName();
7 }

Własności tego interfejsu maja˛ nastepuj


˛ ace
˛ znaczenie:

type Instancja klasy ParameterType, która enkapsuluje pobieranie


parametru.
paramId wartość podana jako parametr ulParam (patrz punkt: 3.8)
wywołań SadGetParam i SadPutParam.
name Nazwa parametru37 .
ParameterType to klasa abstrakcyjna majaca
˛ dwa zadania:

• Przechowuje jako stałe wszystkie inne typy parametrów.


• Enkapsuluje odczyt i zapis parametrów. Podklasy tej klasy musza˛
dokonać implementacji metod:
public abstract T readParam(GenieLibrary library,
DscPointer dscPointer, Parameter param, short
usRecord, short usEntry) throws
ConnectorException;

public abstract void writeParam(GenieLibrary


library, T value, DscPointer dscPointer,
Parameter param, short usRecord, short
usEntry) throws ConnectorException;

Przekazanie parametru library ma na celu umożliwienie podkla-


som wywołanie specjalnej przeładowanej metody SadGetParam38
tak, by JNA dokonała mapowania na typ Javy.
Wszystkie parametry zostały wyekstrahowane z plików nagłówko-
wych i sa˛ dostepne
˛ jako stałe w interfejsie: Parameters39 .
Ponadto parametry, których autor musiał używać, zostały zapisane
jako stałe w klasie ParamAlias z dokładnym opisem i prostsza˛ nazwa.˛
37 Parametry po stronie Genie sa˛ zaimplementowane jako makra preprocesora majace ˛
nastepuj
˛ ac
˛ a˛ konwencje˛ nazewnicza:
˛ CAM_«TYP»_«NAZWA», gdzie typ to znak określajacy
˛
typ parametru (patrz: [13] strona 479), a nazwa jest zwracana przez metode˛ getName
38 lub odpowiednio: SadPutParam
39 Dokładniej sa˛ zdefiniowane w interfejsach Parameters1 i Parameters2 po których

dziedziczy interfejs Parameters. Parametrów jest na tyle dużo że przy próbach zdefin-
iowania ich w jednym interfejsie przekroczony zostaje maksymalny rozmiar bytecodu
klasy.

38
Rysunek 3.8: Schemat UML klasy ErrorDescription

Własność flush Biblioteka Genie nie zapisuje wartości parametrów


w źródle danych aż do wywołania funkcji SadFlush. Klasa GenieCon-
nector ma własność flush, która pozwala kontrolować jej zachowanie
w tym zakresie. Jeśli b˛edzie ona ustawiona na AUTO_COMMIT, to para-
metry b˛eda˛ zapisywane automatycznie zaraz po ustawieniu (domyślnie
jest ona ustawiona na wartość MANUAL).

Obsługa błedów
˛
Za obsług˛e bł˛edów odpowiadaja˛ klasy LibraryWrapper i Simple-
Connector. Wszystkie wywołania funkcji SAD (sa˛ one oznaczone na
diagramach UML) moga˛ wygenerować niesprawdzany wyjatek ˛ klasy
GenieException. Wyjatek˛ ten ma nastepuj
˛ ace
˛ własności:

errorCode Oryginalny kod błedu


˛ zwrócony przez funkcje,
˛ która zgło-
siła bład.
˛
detailedErrorCode Kod bł˛edu zwrócony przez funkcj˛e SadGetSta-
tus, zawierajacy
˛ dokładne informacje o bł˛edzie. (Dokładny opis
sprawdzenia błedów
˛ w [13] rozdział 7).
errorDescription Instancja klasy ErrorDescription zawierajaca
˛ roz-
kodowane informacje z detailedErrorCode.
additionalInfo Dodatkowe informacje (głównie: parametry funkcji
wywołujacej
˛ bład).
˛

Klasa ErrorDescription Klasa ta rozkodowuje informacje zawarte


w kodzie błedu.
˛ Jej schemat jest na diagramie 3.8.
Dodatkowo wyjaśnienia wymaga sposób znajdowania opisu kodu
bł˛edu. Klasa ErrorDescription zawiera statyczna˛ map˛e, w której
kluczami sa˛ specificErrorCodes, a wartościami opisy bł˛edów zacz-
erpni˛ete z [13]. Przeniesiono tylko te kody bł˛edów, z którymi autor si˛e
spotkał. Użytkownicy biblioteki powinni dodawać własne.
Listing statycznej cześci
˛ klasy ErrorDescription.

39
1 private static final Map<Integer, String>
detailedMessages =
2 Collections.synchronizedMap(DefaultedMap.
decorate(new HashMap(), "Nie okreslono
wiadomosci szczegolowej"));
3
4 static {
5 detailedMessages.put(/** kolejne kody bledow */);
6 }

Klasa GenieConnector
Podstawowe różnice z GenieConnector to:
Inne funkcje wywołuja˛ biblioteki Genie funkcje getStatus i isAc-
quiring nie wywołuja˛ metod SAD, lecz tylko zwracaja˛ zapisany
stan.
Dostep
˛ do zapamietanych
˛ wyników pomiarowych Klasa ta udost˛e-
pnia własność lastResult, która zawiera ostatnio zapisane wy-
niki pomiarowe. Jest to własność zwiazana
˛ (patrz 5.3).
Automatyczne odpytywanie DSC Instancje tej klasy automatycznie
co zadany okres (domyślnie 1 sek) odświeżaja˛ parametry DSC —
dokładniej status oraz zebrane dane. Do odpytywania DSC służy
klasa ConnectorStateWatcher dziedziczaca ˛ po klasie java.-
util.Timer.
Wiecej
˛ własności zwiazanych
˛ status oraz acquiring to własności
zwiazane.
˛
Metody odświeżajace
˛ stan (a zatem wykonujace
˛ zapytania SAD) to:
updateStatus() Funkcja ta odświeża własności status i acquiring
updateLastResults() Funkcja ta odświeża własność lastResults
Diagram UML tej klasy jest na rysunku 3.9

Perspektywy rozwoju
W nast˛epnej kolejności można upraszczać używanie z bibliotek Can-
berry:

Uproszczenie korzystania z parametrów Wywołanie funkcji SadGet-


Param wymaga podania 5 argumentów40 . Po stronie Javy wymaga
podania trzech parametrów – instancji interfejsu Parameter i liczb
definiujacych
˛ entry i record. Jednak dla wielu parametrów en-
try i record ustawione sa˛ na stałe, problem polega na tym, że
dla niektórych parametrów oba równaja˛ si˛e 0 (na przykład CAM_-
T_SIDENT) dla innych 1 (np. CAM_L_ADCFANTIC). By oszcz˛edzić
40 Nie licze˛ hDSC, ponieważ de facto jest to obiekt którego parametry pobieramy.

40
Rysunek 3.9: Schemat UML klasy GenieConnector

programiście konieczności pamietania


˛ tych wartości liczbowych,
należałoby umożliwić zapis i odczyt wartości tych parametrów
za pomoca˛ interfejsu zgodnego ze specyfikacja˛ JavaBeans (tj. za
pomoca˛ ’getterów’ i ’setterów)’.

Wymagania modułu
Moduł wymaga zainstalowania pliku DLL zawierajacego
˛ wywołania
statycznych bibliotek Genie; domyślna nazwa pliku DLL to cxAth-
JbzdakGenieConnector. Plik trzeba zainstalować do katalogu Win-
dows/Sytem3241 .

3.9 Moduł encore-symulacja


Moduł ten udostepnia
˛ komponent pozwalajacy˛ na przeprowadzanie
symulacji eksperymentu Comptona. Ponieważ komponent ten ma być
udost˛epniany też jako aplet przez WWW, nie powinien on polegać na
żadnych zewn˛etrznych bibliotekach — mechanizm ładowania apletów
zezwala, co prawda, na pobieranie plików JAR, jednak powinno si˛e mini-
malizować wielkość pobranego apletu. Symulacja pozwala na wybranie
energii padajacych
˛ kwantów γ oraz pozwala na obserwowanie nast˛epu-
jacych
˛ właściwości:

Energie rozproszonego kwantu γ i elektronu w zależności od kata


˛
41 O innych miejscach instalacji czytaj przypis 18

41
Rysunek 3.10: Wyglad
˛ programu do symulacji

Przekroje czynne Ogólnie przekrój czynny określa prawdopodobień-


stwa zajścia określonego zdarzenia kwantowego jeśli cel jest oświe-
tlany strumieniem czastek
˛ o gestości
˛ jedna czastka
˛ na jednostke˛
powierzchni. W symulacji zostało to uproszczone — przekroje
czynne sa˛ modelowane wzgledn ˛ a˛ ilościa˛ zliczeń dla danego kata.
˛
Program pozwala albo na ogladanie
˛ symulacji w zwolnieniu (jedno ani-
mowane zdarzenie na sekund˛e), albo na szybkie wypełnianie (w celu
podgladu
˛ przekrojów czynnych o dużej ilości zliczeń — 100 nieani-
mowanych zdarzeń na sekunde). ˛
Program umożliwia też eksport danych w nast˛epujacych
˛ formatach:
csv Eksport ilości zliczeń i energii w poszczególnych binach.
obrazek Zapisuje zawartość panelu z symulacja˛ jako obrazek.

Aplet
Aplet można obejrzeć na stronie autora: http://skimbleshanks.
ath.cx/inz/encore-symulacja.

3.10 Moduł dies-gui


Moduł zawiera komponenty graficzne. Jest on podzielony na dwa
podmoduły: dies-gui-shared i dies-gui-onSite. Celem tego podzi-
ału jest oddzielenie kodu GUI od kodu zależnego od technicznej im-
plementacji detektorów. Moduł dies-gui-shared należy od modułów

42
genieConnector oraz encore-silniki. Wszelkie dane pobierane z de-
tektorów i operacje wykonywane na silnikach sa˛ wykonywane za pośred-
nictwem instancji interfejsu DetectorsModel. Model ten reprezen-
tuje oba detektory spektrometryczne prowadzace ˛ pomiary dla konkret-
nego kata.
˛ Do modułu dołaczono
˛ bardzo prosty mechanizm dostar-
czania odpowiedniej implementacji tych interfejsów (w zależności od
środowiska uruchomienia). Mechanizm ten (wbudowany w statyczna˛
klas˛e DetectorModelFactory) polega na tworzeniu instancji klasy
o nazwie DetectorsModelImpl, która nie jest zdefiniowana w tym
module (ani nie jest w jego zależnościach!), a implemenentacje klasy
o tej nazwie dostarczane sa˛ moduł dies-gui-shared. Klasa Detector-
ModelFactory na żadanie
˛ tworzy (za pomoca˛ introspekcji42 ) instancje˛
klasy DetectorsModelImpl. Listing klasy DetectorModelFactory:
1 package cx.ath.jbzdak.diesIrae.gui.model;
2
3 import java.lang.reflect.Constructor;
4 import java.util.Collection;
5 import java.util.HashMap;
6 import java.util.Map;
7
8 public class DetectorModelFactory {
9
10 static DetectorsModel currentModel;
11
12 static Map<Integer, DetectorsModel> models = new
HashMap<Integer, DetectorsModel>();
13
14 static private Constructor<DetectorsModel>
modelConstructor;
15
16 static {
17 try {
18 modelConstructor =
(Constructor<DetectorsModel>)
19 Class.forName(
20 "cx.ath.jbzdak.diesIrae.gui.model.
DetectorsModelImpl")
21 .getConstructor(Integer.class);
22 } catch (Exception e){
23 throw new RuntimeException(e);
24 }
25 }
26
27 private static DetectorsModel createModel(int i){
28 try {
29 return modelConstructor.newInstance(i);
30 } catch (Exception e){
42 Introspekcja to api pozwalajace
˛ na programowy dostep
˛ do załadowanych klas oraz
pozwalajace
˛ na wykonwanie na nich operacji

43
31 throw new RuntimeException(e);
32 }
33 }
34
35 public static Collection<DetectorsModel> getModels(){
36 return models.values();
37 }
38
39 public static DetectorsModel
getCurrentDetectorsStateModel(){
40 if(currentModel==null){
41 currentModel = createModel(-1);
42 }
43 return currentModel;
44 }
45
46 public static DetectorsModel getModelForAngle(int
angle){
47 if(!models.containsKey(angle)){
48 models.put(angle, createModel(angle));
49 }
50 return models.get(angle);
51 }
52 }

API refleksji jest wykorzystane w dwóch punktach: w linii 18 tworzy


si˛e obiekt Class dla klasy o nazwie DetectorsModelImpl i z niego
pobiera si˛e obiekt reprezentujacy
˛ konstruktor, pobierajacy
˛ jeden para-
metr typu Integer (reprezentujacy ˛ kat,
˛ dla którego tworzymy model).
W linii 29 za pomoca˛ instancji Constructor tworzy si˛e instancj˛e klasy
DetectorsModel.
Interfejsy modeli danych wygladaj
˛ a˛ nastepuj
˛ aco:
˛
1 public interface DetectorsModel {
2
3 int getAngle();
4
5 void startAcquiring();
6
7 void stopAcquisition();
8
9 boolean isAcquiring();
10
11 void clearData();
12
13 void setPreset(long time, TimeUnit timeUnit);
14
15 long getTime();
16
17 DetectorModel getGammaModel();
18

44
19 DetectorModel getBetaModel();
20
21 }

1 public interface DetectorModel {


2
3 SpectrometricResult getLastResult();
4
5 SimpleRoiDescriptor getRoiDescriptor();
6
7 void clearData();
8
9 //Kalibracja toru spektrometrycznego
10 public LinearFun getCalibration();
11
12 public int getStartChannel();
13
14 public int getEndChannel();
15
16 void addPropertyChangeListener(@NonNull
PropertyChangeListener listener);
17
18 void addPropertyChangeListener(@NonNull String
propertyName, @NonNull PropertyChangeListener
propertyChangeListener);
19
20 void removePropertyChangeListener(@NonNull
PropertyChangeListener listener);
21
22 void removePropertyChangeListener(@NonNull String
propertyName, @NonNull PropertyChangeListener
listener);
23
24 }

3.11 Moduł dies-peakfinder


Moduł umożliwia wyznaczanie pików w zebranych widmach - a
dokładniej dopasowywanie do zaznaczonego obszaru krzywej Gaussa.

Biblioteki, z których korzysta moduł


Moduł korzysta z nastepuj
˛ acych
˛ bibliotek:
JAMA Java Matrix. Implementacja macierzy w j˛ezyku Java. Biblioteka
udostepniona
˛ jako Public Domain.

45
LMA Implementacja algorytmu Levenberga–Marquarda oparta na Nu-
merical Recipies43 . Dostepna
˛ do użytku niekomercyjnego.

Metoda dopasowania
Dopasowanie jest wykonywane metoda˛ Levenberga–Marquarda.
Dopasowujemy funkcje˛ o nastepuj
˛ acym
˛ wzorze:
(x−b)2

f (x) = a · e (2c)2 +d (3.1)

Znaczenie poszczególnych parametrów:

a Wysokość piku.
b Położenie piku
c Odchylenie standardowe.
d Poziom odniesienia piku. Parametr ten powinien niwelować obecność
tła pomiaru.

Poczatkowe
˛ wartości parametrów
Jakość poczatkowych
˛ wartości parametrów dopasowania jest ważna
dla prawdidłowego działania metody Lavenberga–Marquarda. Pocza- ˛
tkowe wartości parametrów zgadywane sa˛ za pomoca˛ nast˛epujacej˛
metody:

a Ilość zliczeń w najwiekszym


˛ kanale.
b Położenie piku wyznaczone ze wzoru:
P
channel_number · counts_in_channel
(3.2)
counts_total

c Odchylenie standardowe wyliczone ze wzoru:


r
X 2 1
counts_in_channel · (channel_number − mean) ·
counts_total
(3.3)
d Wartościa˛ poczatkow
˛ a˛ tego parametru jest 0.

43 “Numerical Recipes in FORTRAN 2nd edition”, p. 676-679, ISBN 0-521-43064X,

1992

46
Rozdział 4

Dystrybucja programu

4.1 Struktura projektu


Program ma standardowa˛ strukture˛ systemu Maven2. Każdy moduł
ma nastepuj
˛ ace
˛ katalogi:

target Zawiera pliki powstałe podczas tworzenia projektu.


src/main/java Zawiera pliki źródłowe
src/main/resources Zawiera pliki zasobów (np. pliki .properties)
src/test/java Zawiera pliki źródłowe testów
src/test/resources Zawiera pliki zasobów (np. pliki .properties)
testów

W module głównym znajduja˛ sie˛ podkatalogi zawierajace


˛ pozostałe
moduły.

4.2 Budowanie projektu


Instalacja systemu Maven
Pakiety z mavenem sa˛ dost˛epne w wi˛ekszości dystrybucji Linuxa.
Dla Ubuntu starczy wykonać polecenie:
sudo aptitude install maven2
R˛eczna instalacja Mavena też nie jest bardzo trudna. Składa si˛e ona
z nastepuj
˛ acych
˛ kroków:

instalacja plików Należy pobrać spakowana˛ dystrybucj˛e mavena ze


strony http://maven.apache.org/download.html oraz rozpa-
kować ja.
˛
ustawienie zmiennej $PATH Należy do zmiennej path dodać położe-
nie podkatalogu bin z katalogu mavena. Na przykład jeśli pliki
rozpakowano do katalogu:
/home/jbzdak/.maven2

47
do zmiennej path należy dodać katalog:
/home/jbzdak/.maven2/bin

ustawienie zmiennej $M2_HOME Należy stworzyć zmienna˛ $M2_HOME,


która wskazuje na katalog, w którym rozpakowano pliki.
ustawienie zmiennej $JAVA_HOME Maven, by działać prawidłowo, musi
być uruchomiony w JDK (a nie JRE), wi˛ec jeśli zmienna $JAVA_-
HOME wskazuje na JRE, należy tak ja˛ zmienić, by wskazywała na
JDK. Ponadto — zmienna ta powinna wskazywać na JDK w wersji
przynajmniej 1.61

Budowanie projektu
Projekt jest budowany za pomoca˛ mavena. By go zbudować, należy
wykonać nastepuj
˛ ac
˛ a˛ sekwencje˛ poleceń:
W kalatogu modułu głównego (dies-irae):
mvn clean install
W katalogu modułu dies-assembly (dies-irae/dies-assembly):
mvn assembly:assembly

4.3 Struktura gotowego programu


W katalogu głównym gotowego znajduje si˛e katalog lib zawierajacy
˛
wszystkie pliki jar oraz plik startowy: dies-irae.bat.

4.4 Edycja projektu


By edytować projekt, należy wykonać odpowiednie kroki w zależności
od IDE. Przed wprowadzaniem zmian w projekcie dobrze jest zapoznać
sie˛ z systemem wersji kontroli GIT2 (polecam szczególnie [19, 20]).

Eclipse
Należy pobrać wtyczki obsługujace
˛ system Maven2 oraz system
wersjonowania kodu GIT.

wtyczki maven2 Znajduja˛ si˛e na stronie http://m2eclipse.sonatype.


org/update/. Należy pobrać wtyczki zaznaczone na rys 4.1.
wtyczka git Znajduje si˛e na stronie http://www.jgit.org/updates/.
1 W szczególności program nie bedzie
˛ sie˛ kompilować (ani uruchamiać) jeśli zmienna
ta bedzie
˛ wskazywać na gcj (gnu java compiler), gdyż środowisko to nie jest zgodne z
Java˛ w wersji 1.6.
2 Rozproszony system kontroli wersji poczatkowo
˛ opracowany na potrzeby rozwoju
jadra
˛ Linuxa.

48
Rysunek 4.1: Przykładowy zrzut ekranu podczas instalacji wtyczek

By otworzyć projekt, należy wejść w menu importu projektów i jako


typ projektu wybrać Existing Maven Projects (rys. 4.2). W nast˛epnym
ekranie należy w polu Project root directory wybrać katalog główny
projektu, wtedy w oknie pod tym polem pojawi si˛e lista projektów do
zaimportowania (rys. 4.3).

Netbeans
Należy zainstalować wtyczki maven oraz nbgit. By otworzyć projekt
należy wybrać “Open project”, a nast˛epnie wybrać katalog główny dies-
irae. Jeśli wtyczka mavena jest zainstalowana poprawnie, katalog
projektu powinien mieć odpowiednia˛ ikone˛ (jak na rys. 4.4).

Intelij idea
Należy zainstalować wtyczki Maven integration i Git integra-
tion.
Ponadto należy zainstalować oprogramowanie GIT na komputerze3 .
By zainstalować GITa w systemie linuksowym, powinno si˛e użyć mene-
dżera pakietów, na przykład dla Ubuntu należy wykonać polecenie:
3 Eclipse i Netbrans używaja˛ implementacji GITa w Javie, natomiast Intelij Idea

używa oryginalnej wersji GITa.

49
Rysunek 4.2: Przykładowy zrzut ekranu podczas importu projektu
Mavena w Eclipse

sudo aptitude install git


Dla Windowsa powinno sie˛ skorzystać z Cygwina4
Ponieważ aplikacja ta była tworzona w tym środowisku, otwiera si˛e
ja˛ jak normalny projekt Idei.

4.5 Wymagania projektu


Budowa projektu
Projekt wymaga JDK5 w wersji przynajmniej 1.6.

Wymagania środowiska uruchomienia


Projekt wymaga JRE w wersji 1.6.
Należy wykonać instrukcje zawarte w punktach 3.7, 3.8.

4 Cygwin to przypominajace˛ Linuksa środowisko dla Microsoft Windows, pozwala ono


kompilować cześć
˛ programów napisanych dla Linuxa tak by działały one w Windowsie.
Zawiera ono również oficjalny port GITa dla Windows.[18]
5 JDK (z ang.) Java Developement Kit

50
Rysunek 4.3: Przykładowy zrzut ekranu podczas importu projektu
Mavena w Eclipse

Rysunek 4.4: Przykładowy zrzut ekranu podczas otwierania projektu


Mavena w Netbeans

51
Rozdział 5

Eksperyment

5.1 Cele ćwiczenia


Zaznajomienie studenta z fizyka˛ eksperymentu Comptona W tym
celu stworzono symulacje˛ eksperymentu, która pozwala szybko
zaznajomić sie˛ z przekrojami czynnymi i zależnościami energety-
cznymi.
Technika pomiarów koincydencyjnych Zaznajomienie studenta z za-
sada˛ (i zasadnościa)
˛ prowadzenia pomiarów z użyciem bloków
koincydencyjnych.
Zasady zachowania Zademonstrowanie, że zasady zachowania ’dzi-
ałaja’.
˛
Przekroje czynne Zbadanie przekrojów czynnych na efekt Comptona.

5.2 Przykładowe sprawozdanie


Kalibracja detektorów
Pierwszym krokiem właściwej cz˛eści pomiarów jest kalibracja de-
tektorów. W bierzacym
˛ układzie detektory sa˛ kalibrowane za pomoca˛
dwóch źródeł kalibracyjnych – źródła CS-137 oraz EU-152. Wzmacnia-
cze powinny być tak ustawione by nawyższemu kanałowi odpowiadała
enegria ok 800keV . W ten sposób optymalnie wykorzystuje si˛e widoczny
przedział widma oraz uzyskuje dość dokładna˛ kalibracj˛e — żródła te
daja˛ na tym zakresie 5 widocznych pików γ.
Zapis ekranu z zebranymi widmami kalibracyjnymi znajduje sie˛ na
rysunku 5.1. Surowe dane znajduja˛ si˛e w tabelach: 5.1 i 5.3; wyniki
kalibracji znajduja˛ si˛e w tabelach: 5.2 i 5.4; wypełniony panel słuacy
˛
do kalibracji programu znajduje sie˛ na rys. 5.2.

Rachunek niepewności pomiarowych


Energie˛ danego piku wyzmnaczamy ze wzoru:

E = a · kan + b (5.1)

52
(a) Widmo kalibracyjne dla detektora wykrywajacego
˛ promieniowanie β w efek-
cie komptona

(b) Widmo kalibracyjne dla detektora wykrywajacego


˛ promieniowanie γ w efek-
cie komptona

Rysunek 5.1: Widma kalibracyjne

Rysunek 5.2: Wypełniony panel kalibracji programu

Energia linii [keV] Numer kanału


122 156
245 299
344 420
660 791
779 925

Tablica 5.1: Surowe dane kalibracyjne detektora β

53
a 0.85
b −11
σa 3 · 10−4
σb 116

Tablica 5.2: Współczynniki kalibracji (E = ax + b) detektora β

Energia linii [keV] Numer kanału


122 157
245 300
344 419
660 784
779 917

Tablica 5.3: Surowe dane kalibracyjne detektora γ

a 0.86
b −14
σa 3 · 10−4
σb 105

Tablica 5.4: Współczynniki kalibracji (E = ax + b) detektora γ

gdzie a i b to współczynniki kalibracji danego detektora, a kan to numer


kanału.
Metoda˛ różniczki zupełnej otrzymujemy wyrażenie na niepewność
pomiarowa: ˛

σE = σa · kan + σkan · a + σb (5.2)


Wartość σkan to odchylenie standardowe odczytane z parametrów
dopasowanegj krzywej gaussa (o metodzie dopasowywania w rozdziale
3.11). Ponieważ wartość σb jest absurdalnie wysoka, postanowiono ja˛
odrzucić.

Zebrane wyniki pomiarów


Tabela 5.5 zawiera wyniki zebrane podczas pomiarów. Każdy wiersz
tej tabeli zawiera wyniki dla jednego z katów,˛ pierwsze trzy kolumny
podaja˛ wyniki dla detektora γ, nastepne trzy dla β; ostatnie dwie koluny
zawieraja˛ zsumowane wyniki.
Wyjaśnienie oznaczeń (litere˛ X należy podmienić na odpowiednio γ
lub β:

σkanX [kan] Odchylenie standardowe krzywej gaussa odczytane z dopa-


sowania. Patrz wzór 5.2. Jednostka˛ wartości z tej kolumny sa˛
kanały detektora.

54
kat
˛ Eγ σkanγ σEγ Eβ σkanγ σkanβ Ecalk σEcalk
[keV] [kan] [keV] [keV] [kan] [keV] [keV] [keV]
0 594 40 34 ?? ?? ?? ?? ??
30 460 30 25 182 21 18 643 43
60 403 131 111 226 81 70 630 181
90 299 49 41 341 52 45 641 86
120 230 25 21 415 31 27 646 48
140 203 21 17 440 23 20 644 38

Tablica 5.5: Zbiorcza tabela wyników

EX [keV] Energia piku


σEX [keV] Niepwność energii piku, wyznaczona ze wzoru 5.2. Wartości
potrzebne do wyznaczenia wyniku znajduja˛ si˛e kolumnie σkanX [kan]
i tabelach 5.4 i 5.2.
Ecalk [keV] Całkowita energia. Suma odpowiednich kolumn.
σEcalk [keV] Niepewność sumy energii z obu detektorów.

Zebrane widma znajduja˛ sie˛ na stronach 58 — 63.

Dyskusja wyników
Duże błedy
˛ widoczne dla niskich katów
˛ wynikaja˛ geometrii pomiaru
(patrz 5.3).
Dla zera stopni nie udało si˛e zlokalizować piku w detektorze β —
wynika to z faktu, że obcina sie˛ w detektorach najmniejsze kanały.

Zasada zachowania energii


Wyniki (w ramach niepewności pomiaru) zgadzaja˛ si˛e z zasada˛ za-
chowania energii. Jednak fakt, że we wszystkich pomiarach wartość
sumy energii czastek
˛ była mniejsza niż oczekiwane 660keV wskazuje na
możliwość błedu
˛ systematycznego.

Zgodność z symulacjami
Wykresy 5.10 i 5.9 przedstawiaja˛ porównanie zmierzonej energii
piku z energia˛ wymodelowana˛ za pomoca˛ przekształconego wzoru 1.6:

E0
E0 = E0
(5.3)
1+ me c 2(1 − cosθ)

Dla niskich katów


˛ — 0 i 30 stopni — ze wzgledu
˛ na duża˛ szerokość
katow
˛ a˛ oraz liczne przypadkowe koincydencje wyniki sa˛ rozbieżne
z przewidywaniami. By owa˛ rozbieżność wyeliminować należałoby
poprawić geometrie˛ pomiarów

55
Dla detektora γ wyniki, poza katem
˛ 0◦ , wyniki zebrane zgadzaja˛ si˛e
z wymodelowanymi z granciach niepewności pomiarowych. Dla katów
powyżej 30◦ stopni zgadzaja˛ si˛e z nimi bardzo dobrze. Dla detektora
β natomiast widać lekka˛ tendencj˛e zaniżania wyników zmierzonych,
wzgl˛edem wymodelowanych. Wyniki obu detektorów sa˛ zgodne, w ra-
mach niepewności pomiarowych, z przewidwyaniami teoretycznymi.

5.3 Peryspektywy rozwoju


Poprawa geometrii pomiarów
Detektory sa˛ zbyt blisko od siebie i od źródła ma to nast˛epujace
˛
konsekwencje:
Duża szerokość katowa
˛ detektorów jest ona rz˛edu 10◦ − 15◦ . Powo-
duje to na przykład niemożliwość dokładnych pomiarów dla 0◦ .
Przypadkowe koincydencje dla niskich katów
˛ Drugi detektor może
rejestrować koincydencje powodowane złapaniem w detektorze γ
kwantu pochodzacego
˛ ze źródła
Uwypukla obietościow
˛ a˛ nature˛ detektorów Model zjawiska Comptona
zakłada, że zdarzenie zajdzie w jednym punkcie przestrzeni, pod-
czas gdy zjawisko może zajść w dowolnym miejscu detektora
majacego
˛ niemała˛ obj˛etość. Dodatkowo obniża to dokładność
ustalenia kata.
˛
Oddalenie detektorów od siebie wymagało by natomiast o wiele
silniejszych źródeł promieniotwórczych.

Pomiary dwuparametryczne
Bierzace
˛ oprzyrzadowanie
˛ umożliwia zbieranie pojedyńczych widm,
tj. punkt danych zawiera zliczenie jednego detektora, podczas gdy
w urzadzeniach
˛ wielopparametrycznych punkt danych zwiera zliczenia
kilku detektorów. Po zastosowaniu urzadzenia˛ dwuparametrycznego
w eksperymencie, można wykreślić pomiary z jednego detektora w
funkcji pomiarów z drugiego. Eksperyment Comptona byłby w tym
wzgl˛edzie bardzo dydaktyczny, ponieważ jego dwuparametryczne widmo
jest dość proste i ma przejrzysta˛ interpretacj˛e; na widmie tym powin-
niśmy zobaczyć prosta. ˛
Pierwsze testy urzadzenia
˛ dwuparametrycznego zostały już wyko-
nane i dały zadowalajace ˛ wyniki. Przykładowe wyniki załaczone
˛ na
rysunkach: 5.11 i 5.12.
Do pełnego wdrożenia urzadzenia
˛ dwumarametrycznego należy
wykonać nastepuj
˛ ace
˛ prace:
Oprogramowanie urzadzenia
˛ w Javie W tej chwili urzadzenie
˛ jest
oprogramowane w VisualBasicu.
Opracowanie wizualizacji danych Załaczone
˛ obrazki powstały w Root’cie.
Wizualizacje˛ należałoby wykonać w Javie.

56
Właczenie
˛ comptona do internetowego laboratorium fizyki
Eksperyment Comptona zarazem jest eksperymentem bardzo dydak-
tycznym, jak i w pełni zautomatyzowanym — po dokonaniu kalibracji
nie wymagana jest fizyczna ingerencja w układ — wi˛ec naturalnym
krokiem zdaje si˛e właczenie
˛ go do Internetowego Laboratorium Fizyki.

57
(a) Detektor β, zaznaczony obszar patrz 5.2

(b) Detektor γ

˛ 0◦
Rysunek 5.3: Widma dla kata

58
(a) Detektor β

(b) Detektor β, wesja bez marker a ROI (dla czytelności)

(c) Detektor γ

˛ 30◦
Rysunek 5.4: Widma dla kata

59
(a) Detektor β

(b) Detektor γ

˛ 60◦
Rysunek 5.5: Widma dla kata

60
(a) Detektor β

(b) Detektor γ

˛ 90◦
Rysunek 5.6: Widma dla kata

61
(a) Detektor β

(b) Detektor γ

˛ 120◦
Rysunek 5.7: Widma dla kata

62
(a) Detektor β

(b) Detektor γ

˛ 140◦
Rysunek 5.8: Widma dla kata

Rysunek 5.9: Porównanie wartości modelowych i otrzymanych dla


detektora γ

63
Rysunek 5.10: Porównanie wartości modelowych i otrzymanych dla
detektora β

Rysunek 5.11: Nieoczyszczone widmo dwuparametryczne w ekspery-


mencie Comptona. Wyrkes wykonany przez mgr inż. Pawła Hładkiego.

Rysunek 5.12: Oczyszczone widmow dwuparametryczne w eksperymen-


cie Comptona. Wyrkesy wykonane przez mgr inż. Pawła Hładkiego.

64
Bibliografia

[1] Janusz Araminowicz, Krystyna Małuszyńska, Marian Przytuła;


“Laboratorium Fizyki Jadrowej”;
˛ Warszawa 1978 PWN
[2] M. H. Pirenne; “The diffraction of X-Rays and elec-
trons by free molecules”; Cambrige University Press
1946; Dost˛epne w serwisie Google Books pod adresem:
http://books.google.pl/books?id=OIM6AAAAMAAJ&q=
H.+Pirenne%3B+%60%60The+diffraction+of+X-Rays+
and+electrons+by+free+molecules%27%27&dq=H.
+Pirenne%3B+%60%60The+diffraction+of+X-Rays+and+
electrons+by+free+molecules%27%27&lr=&ei=CaJIS_
nKApTIzAS0i-z0DQ&client=firefox-a&cd=1 (adres skrócony:
http://tinyurl.com/diffractionByMolecules).
[3] Canberra; “Model 3125 Dual 0-5kV HVPS user’s manual”;
[4] Canberra; “Model 2007P PM Tube Base/Preamp user’s manual”;
[5] Canberra; “Model 802 Scincillation Derectors user’s manual”;
[6] Canberra; “Model 2007P Spectroscopy Amplifier user’s manual”;
[7] Canberra; “Multiport II Multichannel Analyzer user’s manual”;
[8] Strona domowa projektu Apache Maven;
http://maven.apache.org/what-is-maven.html; dost˛ep z dnia
25-10-2009r.
[9] Strona domowa projektu Apache Maven; http://maven.apache.
org/; dostep
˛ z dnia 21-09-2009r.
[10] Tim O‘Brien, Jason von Zyl i inni; Maven the definitive
Guide, wersja 0.71; O‘Reily; dost˛epne w internecie pod
adresami: http://www.sonatype.com/maven/documentation/
download-book?file=books/maven-definitive-guide.pdf,
oraz kopia na moim serwerze http://jbzdak.ath.cx/inz/
maven-definitive-guide.pdf;
[11] POM Reference; http://maven.apache.org/pom.html; dostep
˛ z
dnia 21-09-2009r.
[12] Specyfikacja Java Beans wersja 1.01; http://java.sun.com/
javase/technologies/desktop/javabeans/docs/spec.html

65
[13] Canberra Software; S560 Programming Library User’s Manual;
materiały dostarczone przez producenta; tłumaczenie własne.
[14] Sun Microsystems; Java Native Interface Specification;
http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/
design.html#wp715; dostep
˛ z dnia 21-09-2009r.
[15] Strona projektu JNA; https://jna.dev.java.net/; dostep
˛ z
dnia 21-09-2009r.
[16] A. H. Compton; Wykład wygłoszony podczas otrzymywa-
nia ngrody Nobla; Dost˛epne w internecie pod adresem:
http://nobelprize.org/nobel_prizes/physics/laureates/
1927/compton-lecture.pdf; dostep
˛ z dnia 17-10-2009r.
[17] David Resnick, Robert Halliday; “Fizyka 2”; Warszawa 2001 PWN;
ISBN 83-01-0924-2
[18] Strona domowa projektu Cygwin; http://www.cygwin.com/;
dostep
˛ z dnia 25-10-2009r.
[19] O projekcie git; http://git-scm.com/about; dost˛ep z dnia 25-
10-2009r.
[20] Wielu autorów; “Git community book”; http://book.git-scm.
com/; dostep
˛ z dnia 25-10-2009r.

66
Spis rysunków

1.1 Geometria zderzenia comptonowskiego. Opracowanie własne. 1


1.2 Zależności energetyczne i katowe˛ dla padajacego
˛ kwanta
gamma o energii 0.01M eV . Opracowanie własne. . . . . . . . 4
1.3 Zależności energetyczne i katowe˛ dla padajacego
˛ kwanta
gamma o energii 0.660M eV . Opracowanie własne. . . . . . . 5
1.4 Zależności energetyczne i katowe˛ dla padajacego
˛ kwanta
gamma o energii 1,13M eV . Opracowanie własne. . . . . . . . 6
1.5 Przekroje czynne i rozkłady katowe ˛ za [1, str 65] . . . . . . . 6
1.6 Schemat oryginalnego układu pomiarowego Comptona [2, rys
16] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.7 Wyniki Comptona[2, rys 16] . . . . . . . . . . . . . . . . . . . 7

2.1 Geometria eksperymentu [1] . . . . . . . . . . . . . . . . . . . 8


2.2 Zdjecie
˛ układu . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.3 Schemat elektronicznej cześci
˛ układu. . . . . . . . . . . . . . 10

3.1 Schemat UML klasy EngineDriver . . . . . . . . . . . . . . . . 23


3.2 Schemat UML klasy CommandDriver . . . . . . . . . . . . . . 24
3.3 Klasa PositionDriver . . . . . . . . . . . . . . . . . . . . . . . . 26
3.4 Klasa CalibratedDriver . . . . . . . . . . . . . . . . . . . . . . 26
3.5 Schemat UML klasy SimpleConnector . . . . . . . . . . . . 36
3.6 Schemat stanów klasy SimpleConnector . . . . . . . . . . . 36
3.7 Schemat stanów klas zawierajacych˛ wyniki pomiarów spek-
trometrycznych . . . . . . . . . . . . . . . . . . . . . . . . . . 37
3.8 Schemat UML klasy ErrorDescription . . . . . . . . . . . . 39
3.9 Schemat UML klasy GenieConnector . . . . . . . . . . . . . 41
3.10 Wyglad
˛ programu do symulacji . . . . . . . . . . . . . . . . . 42

4.1 Przykładowy zrzut ekranu podczas instalacji wtyczek . . . . 49


4.2 Przykładowy zrzut ekranu podczas importu projektu Mavena
w Eclipse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
4.3 Przykładowy zrzut ekranu podczas importu projektu Mavena
w Eclipse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
4.4 Przykładowy zrzut ekranu podczas otwierania projektu Mavena
w Netbeans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51

5.1 Widma kalibracyjne . . . . . . . . . . . . . . . . . . . . . . . 53


5.2 Wypełniony panel kalibracji programu . . . . . . . . . . . . . 53
˛ 0◦ . . . . . . . . . . . . . . . . . . . . . . . . .
5.3 Widma dla kata 58

67
5.4 Widma dla kata˛ 30◦ . . . . . . . . . . . . . . . . . . . . . . . . 59
5.5 Widma dla kata˛ 60◦ . . . . . . . . . . . . . . . . . . . . . . . . 60
5.6 Widma dla kata˛ 90◦ . . . . . . . . . . . . . . . . . . . . . . . . 61
5.7 Widma dla kata˛ 120◦ . . . . . . . . . . . . . . . . . . . . . . . . 62
5.8 Widma dla kata˛ 140◦ . . . . . . . . . . . . . . . . . . . . . . . . 63
5.9 Porównanie wartości modelowych i otrzymanych dla detek-
tora γ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
5.10 Porównanie wartości modelowych i otrzymanych dla detek-
tora β . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
5.11 Nieoczyszczone widmo dwuparametryczne w eksperymencie
Comptona. Wyrkes wykonany przez mgr inż. Pawła Hładkiego. 64
5.12 Oczyszczone widmow dwuparametryczne w eksperymencie
Comptona. Wyrkesy wykonane przez mgr inż. Pawła Hładkiego. 64

68
Załaczniki
˛

Słownik terminów programistycznych


Własność (z ang. property) jakiegoś obiektu w rozumieniu specyfikacji
Java Beans.
Własność zawiazana
˛ (z ang. bound property) jakiegoś obiektu w rozu-
mieniu specyfikacji Java Beans — tj. własność, której zmiana
spowoduje wywołanie PropertyChangedEventa.

Oznaczenia na diagramach UML


«SAD call» Oznacza to, iż dana funkcja wykonuje wywołanie funkcji
SAD (o funkcjach SAD na stronie: 27). Gdy tym stereotypem oz-
naczono własność, oznacza to, że funkcje set lub/i get wywołuja˛
metody SAD.
«bound» Oznacza, że dana własność jest własnościa˛ zwiazan
˛ a˛ (patrz
5.3).
«final» Oznacza, że dane pole klasy jest zadeklarowane jako final.
Na własności (patrz 5.3) oznacza również, że dana własność jest
tylko do odczytu.
«immutable» Na klasie oznacza, że instancje danej klasy sa˛ niezmi-
enne — tj. albo nie posiadaja˛ stanu, albo ich stan jest niezmienny.

Generowanie bibliotek dll ze statycznych


Autor nie znalazł bezpłatnych narz˛edzi konwertujacych˛ biblioteki
statyczne na biblioteki dll. Należy zatem recznie
˛ stworzyć plik dll. Na-
jpierw należy stworzyć w Visual Studio1 projekt dll. Nast˛epnie należy
skopiować do niego konieczne pliki nagłówkowe oraz pliki bibliotek
statycznych z biblioteki S560.
Wreszcie należy stworzyć same pliki tworzace
˛ dynamiczne opakowa-
nie dla statycznej biblioteki. Należy dla każdej funkcji SAD stworzyć
funkcje˛ opakowujac˛ a,
˛ tj. dla funkcji:
1 Canberra sugeruje konkretna˛ wersje˛ tego środowiska i kompilatora, jednak
ponieważ sugerowana jest przestarzała wersja, która nie jest dostepna
˛ za darmo.
Postanowiłem używać darmowego Visual Studio 2008 Express.

69
SADENTRY SadCreateDSC(void * pstCfg, HMEM *
phDSC, FLAG fAdv, HWND hWin );
należy stworzyć deklaracje˛ funkcji (w pliku .h:
SADENTRY DLL_WRAPPER_SadCreateDSC(void * pstCfg,
HMEM * phDSC, FLAG fAdv, HWND hWin);
oraz jej definicje˛ (w pliku: .cpp):
extern "C"{
__declspec(dllexport) short
DLL_WRAPPER_SadCreateDSC(void * pstCfg, HMEM *
phDSC, FLAG fAdv, HWND hWin){
return SadCreateDSC(pstCfg, phDSC, fAdv, hWin);
}

Uwaga: nazwy wygenerowanych funkcji Jednym z problemów, na


jaki można si˛e natknać
˛ podczas generowania dll, jest problem deko-
rowania nazw polegajacy
˛ na tym, że kompilatory dodaja˛ specjalne deko-
racje do nazw wygenerowanych funkcji w skompilowanych plikach.
Po pierwsze kompilatory C++, by umożliwić przeładowywanie nazw
dodaja˛ pewne dekoracje. Należy wi˛ec definicje funkcji opakowanych
umieścić wewnatrz
˛ deklaracji:
extern "C"
by ten rodzaj dekoracji wyłaczyć.
˛
Ponadto sam Windows domyślnie dokonuje dekoracji nazw. Dlatego
też w opcjach kompilatora należy wyłaczyć
˛ wszelkie dekoracje nazw.
Uwaga: makro SADENTRY którym dekorowane jest każde wywołanie
funkcji SAD, zawiera deklaracj˛e dekorowania nazw, która spowoduje
właczenie
˛ dekorowania również wtedy gdy w kompilatorze były one
wyłaczone,
˛ należy zatem nie zostawić makra SADENTRY przed wygen-
erowanymi funkcjami. Makro to jest definiowane jako:
#define SADENTRY short WINAPI
wiec
˛ zupełnie bezpiecznie można zamienić je na short — typ zwracany
przez każda˛ metode˛ SAD.
Do wygenerowania samych plików zawierajacych˛ funkcje opakowu-
jace
˛ można wykorzystać klas˛e: WrapperGenerator, która jest dost˛epna
w projekcie w module wrapper-generator2 .
By stworzona biblioteka zawierała wszystkie metody potrzebne do
działania modułu genie-connector, należy stworzyć funkcje opako-
wujace
˛ dla wszystkich metod z plików Sad.h i Utility.h.

2 Można ja˛ też pobrać ze strony: http://stackoverflow.com/questions/845183/

70

You might also like