на тему рефераты
 
Главная | Карта сайта
на тему рефераты
РАЗДЕЛЫ

на тему рефераты
ПАРТНЕРЫ

на тему рефераты
АЛФАВИТ
... А Б В Г Д Е Ж З И К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Э Ю Я

на тему рефераты
ПОИСК
Введите фамилию автора:


Дипломная работа: Использование ЭВМ в кардиологии


Все Windows – приложения являются программами, управляемыми событиями (event-driven applications), что коренным образом отличает их от программ с фиксированной последовательностью выполнения. Программы, управляемые событиями, обладают большей гибкостью в смысле выбора пользователем порядка выполнения операций. Однако разработчик не может заранее предсказать последовательность вызовов функций и даже выполнения операторов своего приложения, так как эта последовательность определяется на этапе выполнения кода. Характерно то, что последовательность большей частью определяется не программой, а системой Windows и зависит от потока сообщений о событиях в системе. Большую часть времени приложение, управляемое событиями, находится в состоянии ожидания событий, точнее, сообщений о событиях. Сообщения могут поступать от различных источников, но все они попадают в очередь системных сообщений. Только некоторые из них система передаст в очередь сообщений вашего приложения. Все это время приложение выполняет цикл ожидания сообщений. Как только придет сообщение, адресованное вашему приложению, система передаст управление вашей оконной процедуре. Можно отметить факт, что в случае многопотокового приложения (multithreaded application) сообщение приходит активному потоку (thread) приложения.

Наступление события обозначается поступлением сообщения. Все сообщения Windows имеют стандартные имена, многие из которых начинаются с префикса WM_ (Windows Message). Например, WM_PAINT именует сообщение о том, что необходимо перерисовать содержимое окна того приложения, которое получило это сообщение. Идентификатор сообщения WM_PAINT – это символьная константа, обозначающая некое число.

Рассмотрим такой пример. Пользователь приложения нажимает клавишу на клавиатуре, а система вырабатывает сообщение об этом событии. Вы знаете, что Windows обеспечивает поддержку клавиатуры, не зависящую от типа устройства (device – independent support). Для каждого типа клавиатуры она устанавливает соответствующий драйвер, то есть специальную программу, которая служит посредником между клавиатурой и операционной системой. Клавиатурная поддержка Windows не зависит также от языка общения с системой. Это достигается использованием специальной клавиатурной раскладки (layout), которую пользователь выбрал в данный момент. Каждой клавише присвоено уникальное значение – идентификатор клавиши, зависящий от типа устройства и называемый скан – кодом. Когда пользователь вводит символ, то клавиатура генерирует два скан кода: один – когда он нажимает клавишу, и другой – когда отпускает. Скан коды с клавиатуры поступают в клавиатурный драйвер, который, используя текущую раскладку, транслирует их и преобразует в сообщения.

Клавиатурный драйвер интерпретирует скан – код и преобразует его в определяемый Windows код виртуальной клавиши (virtual - key code), не зависящий от типа устройства и идентифицирующий функциональный смысл клавиши. После этого преобразования скан - кода драйвер создает сообщение, в которое включается: скан – код, виртуальный код и другая информация о нажатии клавиши, и помещает его в очередь системных сообщений. Windows выбирает сообщение из этой очереди и посылает его в очередь сообщений соответствующего потока (thread). В конце концов цикл выборки сообщений данного потока передает его соответствующей оконной процедуре для обработки. Модель вызова с клавиатуры в системе Windows представлена на рис. 3.1.

Рис. 3.1 Схема генерации и движения сообщений Windows.

Рассмотренная модель выработки и прохождения сообщений поможет вам понять структуру, принятую во всех Windows – приложениях. Последние два блока в рассмотренной схеме определяют особенности строения любого Windows – приложения. Простейшее приложение состоит как минимум из двух функций:

- функция WinMain (имя зарезервировано), которая содержит цикл выборки сообщений и выполняется первой в любом приложении;

- оконная процедура, которую вызывает система, направляя ей соответствующие сообщения.

Имя оконной процедуры выбирается произвольно. Система Windows регистрирует это имя, связывая его с вашим приложением. Также безусловно нужно отметить, что хотя в приложениях на основе MFC трудно увидеть функцию WinMain или оконную процедуру, они там присутствуют, но скрыты от программиста разработчиками среды Visual Studio.

Главное окно приложения.

На рис. 3.2 приведено главное окно приложения. Через набор управляющих элементов производится управление основной программой.

Элементы управления:

-  Кнопка “Загрузить файл” – реализует загрузку оцифрованного и упакованного файла ЭКГ диаграммы (рис. 2), хранящегося на диске и отображает распакованные данные в окне просмотра (рис. 3).

-  Кнопка “Выход” – выйти из приложения.

-  Комбинированное поле фильтров – Выбор фильтра для последующего отображения в окне просмотра.

-  Флажок переключатель ”Фильтр пробка” – установка режима фильтрации сетевой наводки (игнорирует выбор фильтра в комбинированном поле).

-  Флажок переключатель “Дифференциатор” – устанавливает режим определения подачи импульсов дефибриляции.

-  Комбинированное поле отведений – Выбор номера отведения для отображения в окне просмотра.

-  Кнопка “применить” – устанавливает режим отображения отфильтрованного сигнала в окне просмотра (работает после загрузки файла).

Рис. 3.2 Главное окно приложения.


Загрузка файла.

Прежде чем на экране появится второе окно с данными баз ЭКГ, в программе необходимо загрузить один из файлов *.@8. В функции, реагирующей на нажатие кнопки “Загрузить файл” используется стандартный диалог выбора файла для загрузки, далее выбранный файл передается в функцию, выделяющую массивы значений всех двенадцати отведений. После этого здесь же конструируется окно просмотра с неинициализированной фильтрованной ЭКГ.

void CNewvisualDlg::OnLoadFile()

{

//конструктор файлового диалога

CFileDialog dlg(TRUE,NULL,NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,"Экг диаграммы(*.@8)|*.@8||");

//сделать модальным и запомнить состояние

int response = dlg.DoModal();

if(response = IDOK)

{

CString fname=dlg.GetFileName();

if(fname=="") goto end;

HANDLE InputFile = CreateFile(fname,GENERIC_READ,FILE_SHARE_READ,

0,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,0);

//распаковать и выделить 12 отведений

ReadK12(InputFile);

//создать окно просмотра

m_dlgPaint.Create(IDD_VIEW_GRAPH,this);

m_dlgPaint.SetWindowPos(&wndTop,200,0,m_dlgPaint.right*0.8,

m_dlgPaint.left-100,SWP_SHOWWINDOW);m_dlgPaint.ShowWindow(SW_SHOW);//показать окно

m_dlgPaint.Counter = 0;

SetTimer(ID_SHOW_TIMER,2,NULL);

memcpy(m_dlgPaint.StartOtv,StartOtv[0],16000);

Flag = true;

UpdateData();

m_dlgPaint.Invalidate();

}

end:

;;

}

Дальше более интересно было бы рассмотреть алгоритм выделения отведений из файлов баз ЭКГ. У файлов *.@8 первые 53 байта содержат заголовочную информацию для параметров ЭКГ(время снятия ЭКГ, тип ЭКГ, частота сигнала и т.д.). Взятие дальнейшей информации идет в зависимости от типа ЭКГ, если ЭКГ сжата, то работает алгоритм сжатия, если не сжата, то данные берутся элементарным способом.

Окно просмотра ЭКГ диаграмм.

Окно просмотрареализует отображение ЭКГ диаграмм в режиме

прокрутки, в соответствии с реальным временем снятия ЭКГ сигнала (рис 2).

Режим прокрутки реализуется при помощи установки таймера функцией SetTimer(ID_SHOW_TIMER,2,NULL), где 2 – время в миллисекундах посыла сообщения от таймера к системе. Поскольку частота съема данных ЭКГ равна 500 Гц. , то здесь прокрутка реализована со скоростью отрисовки в один пиксел на каждый посыл сообщения от таймера. Алгоритм работы таймера будет рассмотрен ниже.

компьютерный программный импульс дефибриляция


Рис.3.3 Окно просмотра ЭКГ диаграмм (Неотфильтрованный и отфильтрованный сигнал)

В данном окне используется два режима работы; режим показа сигнала из файла загрузки, режим показа как сигнала из файла загрузки, так и отфильтрованного сигнала, в соответствии с установками управляющих элементов. Для вывода данных ЭКГ на экран была написана динамически подключаемая графическая библиотека Graph.dll, которая может использоваться в других приложениях. Созданный динамический модуль система интегрирует в пространство другого(клиентского) процесса, загрузив его по определенному базовому адресу. Мы воспользуемся преимуществом, которое предоставляет библиотека MFC, расширяющая WIN32 – поддержку DLL. DLL – расширение способно экспортировать не только отдельные функции, но и целые классы C++. Приложение, использующее DLL(клиентское приложение), может создавать объекты импортируемого класса, а так же создавать производные классы на основе класса, реализованного в DLL. Обычные DLL могут экспортировать функции. DLL-расширения могут экспортировать как функции, так и классы.

DLL – расширение динамически связывается с кодом DLL – версии библиотеки MFC и требует, чтобы клиентская программа тоже компоновалась с ним динамически. Обычная DLL может связываться с библиотекой MFC как динамически, так и статически. Но это не снижает привлекательности DLL – расширений, так как при необходимости можно поставить заказчику необходимые системные DLL, такие как Mfc42d.dll, Mfc042.dll и другие.

Исходный код определения экспортируемого класса приведен ниже.

class AFX_EXT_CLASS CGraph

{

double dXLeft;// Левый верхний угол

double dYTop;

double dFracX;// Ширина и высота

double dFracY;

double dMinX, dMaxX;// Min-Max значения по горизонтали

double dMinY, dMaxY;// Min-Max значения по вертикали

double dSpanX;// Размах графика по горизонтали

double dSpanY;// Размах графика по вертикали

double dStepX, dStartX;// Шаг и начальное значение

double dStepY, dStartY;

UINT nPoints;// Количество точек

// Целочисленные аналоги

UINT nStepsX, nStepX, MinX, MaxX;

UINT nStepsY, nStepY, MinY, MaxY;

UINT *X, *Y;// Координаты точек на экране

int iPowerX, iPowerY;// Экспоненты

CRect rect;// Прямоугольник вывода

// Три типа шрифтов: для осей, заголовка и экспонент

CFont TextFont, TitleFont, PowerFont;

public:

void GetRect(int&,int&,int&,int&); //получить размер прямоугольника отображения

Cgraph (CRect, UINT, double ,double ,double ,double);//конструктор

// Функции нормировки исходных массивов

void ScaleX(TValues&);

void ScaleY(TValues&);

// Масштабирование массива

void Scale (double, int&, double&);

// Изображение координатной сетки

void DrawGrid (CDC*, CString&, CString&, CString&, TValues&, TValues&);

// Изображение графика зависимости

void DrawFunc (CDC*,BYTE *);

virtual ~CGraph ();

};

В конструкторе мы инициализируем область вывода графика, количество отображаемых точек и коэффициенты вывода, относительно общей области. Далее в основном приложении для вывода графики нам понадобятся функции DrawGrid и DrawFunc. Масштабирование входных координат точек графика, задаваемых числами с плавающей точкой двойной точности, производится в функции Scale, где значения по осям Х и Y масштабируются отдельно через вызовы функций ScaleX и ScaleY. Функция DrawGrid выводит на экран координатную сетку, а функция DrawFunc рисует график.

Класс Filters.

Класс Filters реализует хранение и расчет данных для фильтрации ЭКГ.

class Filters

{

public:

char Name[10];// название фильтра

double * Coeficients;//коэффициенты фильтра с плавающей точкой

short * QuantizCoeficients;//целочисленные коэффициенты

BYTE NumCoef;// число коэфициентов

//конструктор

Filters(char * FilterName,BYTE NumCoeficientsdouble,double * Coef = NULL,double * Quant = NULL);

// функция расчета КИХ фильтров

void GetType_1(short * InBuffer,short * OutBuffer);

// функция рассчета БИХ фильтров

void GetType_2(short * Inbuffer,short * Outbuffer);

// функция рассчета фильтров с приведением

// к целочисленным коэфициентам

void GetQType(short * Inbuffer,short * Outbuffer,BOOL Type,BYTE PreCoef = 0);

~Filters();// деструктор

};

В конструкторе происходит инициализация названия фильтра, числа коэффициентов, самих коэффициентов в зависимости от типа фильтра.

Предварительная обработка сигнала в электрокардиографии заключается, в основном, в цифровой фильтрации сигнала и его усреднении. Цель фильтрации – подавление неблагоприятных факторов, таких как шумы, выделение определенных характеристик сигнала и его коррекция. Наиболее простой в реализации и достаточно эффективной является линейная инвариантная к сдвигу фильтрация. С точки зрения реализации (впрочем, это является общепринятым в теории ЦОС ) разумно разделить линейные цифровые фильтры на 2 типа: фильтры с конечной импульсной характеристикой (КИХ) и фильтры с бесконечной импульсной характеристикой (БИХ). По-другому они называются нерекурсивный и рекурсивный соответственно.

Фильтры с конечным импульсным откликом описываются следующим уравнением:


Соответственно, передаточная функция таких фильтров выглядит следующим образом:


Передаточная функция не имеет полюсов, следовательно, фильтр всегда устойчив, более того, если ряд коэффициентов симметричен, то фильтр имеет линейную ФЧХ. КИХ - фильтры обычно реализуются в такой же форме, как и определяются, т.е. в виде суммы.

Фильтры с бесконечным импульсным откликом описываются следующим выражением:


Передаточная функция имеет вид:



Существует достаточно много типов БИХ фильтров, классифицируемых прежде всего по форме передаточной характеристики: Баттерворта, Чебышева, эллиптический.

Цифровые фильтры обычно проектируются в соответствии с определенными требованиями, предъявляемыми обычно к передаточной функции, которая, естественно, определяется конкретной задачей, для которой разрабатываемый фильтр и предназначен. Идеальные фильтры не реализуемы, поэтому приходится говорить лишь о соответствии фильтра параметрам в рамках допустимой ошибки. Для расчета цифровых фильтров существует несколько методик, требующих различных вычислительных возможностей. В электрокардиографии обычно применяют фильтры какого – либо одного типа и для определенной частоты среза и частоты дискретизации. Поэтому расчет фильтра в реальном времени проводить обычно не требуется, а коэффициенты рассчитываются при помощи какого – либо пакета, позволяющего сделать это визуально и интерактивно (в данном дипломном проекте расчеты проводились в среде Matlab v.6.0).

Функции КИХ и БИХ фильтрации:

//Функция КИХ фильтрации

void Filters::GetType_1(short * InBuffer,short * OutBuffer)

{

WORD i = 0;

double Temp = 0;

while(i<8000)

{

if(i<NumCoef) OutBuffer[i] = InBuffer[i];

else

{

for(BYTE j = 0;j<NumCoef;j++)

Temp += InBuffer[i-j]*Coeficients[j];

OutBuffer[i] = (short)Temp;

}

Temp = 0.0;

i++;

}

}

//Функция БИХ фильтрации

void Filters::GetType_2(short * Inbuffer,short * Outbuffer)

{

WORD i = 0;

double Temp = 0;

while(i<8000)

{

if(i<(NumCoef/2 - 1)) Outbuffer[i] = Inbuffer[i];

else

{

for(BYTE j = 0;j<(NumCoef/2);j++)

Temp += (Inbuffer[i-j]*Coeficients[j]

- Outbuffer[i-j]*Coeficients[j+NumCoef/2]);

Outbuffer[i] = (short)Temp;

}

Temp = 0;

i++;

}

}

Если тип фильтра – БИХ, тогда коэффициенты обратной связи ак в конструкторе нужно передавать сразу за коэффициентами bm.

В связи с тем, что последующая реализация тестируемых фильтров будет производиться на микроконтроллере Siemence без реализации арифметики с плавающей точкой, необходимо реализовать фильтрацию с целочисленными коэффициентами. Реализация целочисленных коэффициентов производится в функции GetQType. В конструктор передаются коэффициенты с плавающей точкой, рассчитанные в среде Matlab при условиях квантизации, которые при перемножении на число два в пятнадцатой степени дают целочисленные коэффициенты. Соответственно после фильтрации все точки ЭКГ масштабируются к исходным значениям.

//Функция фильтрации с целочисленными коэффициентами

void Filters::GetQType(short * Inbuffer,short * Outbuffer,BOOL Type,BYTE PreCoef)

{

WORD i = 0;

int Temp = 0;

while(i<8000)

{

if(i<(NumCoef/2 - 1)) Outbuffer[i] = Inbuffer[i];

else

{

for(BYTE j = 0;j<(NumCoef/2);j++)

if(Type == FALSE)

Temp += (int)(Inbuffer[i-j]*(short)QuantizCoeficients[j]);

else

Temp += (Inbuffer[i-j]*QuantizCoeficients[j]

-Outbuffer[i-j]*QuantizCoeficients[j+NumCoef/2]);

if(Temp>0)

Outbuffer[i] = (short)( Temp >> (15+PreCoef) );

else

Outbuffer[i] = -(short)( (-Temp) >> (15+PreCoef) );

}

Temp = 0;

i++;

}

}

Первый параметр функции – входной массив графика, второй параметр – массив в который будут передаваться отфильтрованные значения, третий параметр – тип фильтра (БИХ или КИХ), четвертый параметр – коэффициент масштабирования отфильтрованных значений выходного массива.

Реализация таймера.

При успешной загрузке данных из файла устанавливается системный таймер с временем срабатывания (в миллисекундах), равным 2. Таймеры являются лимитированным глобальным ресурсом системы, поэтому следует проверять код, возвращаемый функцией SetTimer. После установки таймера каждые 2 миллисекунды система будет посылать в очередь сообщений нашего приложения сообщение WM_TIMER. Значение третьего параметра NULL говорит о том, что сообщение будет обрабатываться в оконном классе, а не в специально созданной глобальной функции, адрес которой следовало бы передать третьим параметром. При возникновении прерывания от таймера управление будет передано в функцию OnTimer.

void CNewvisualDlg::OnTimer(UINT nIDEvent)

{

if(Flag == true)

{

if(m_dlgPaint.NPoints == 500)

m_dlgPaint.NPoints = (m_dlgPaint.x2 - m_dlgPaint.x1);

else

{

m_dlgPaint.NPoints+=(m_dlgPaint.x2 - m_dlgPaint.x1);

m_dlgPaint.PointCounter+=(m_dlgPaint.x2 - m_dlgPaint.x1);

}

m_dlgPaint.rect.left = m_dlgPaint.x1-5;

m_dlgPaint.rect.right = m_dlgPaint.x1;

m_dlgPaint.rect.top = m_dlgPaint.y1;

m_dlgPaint.rect.bottom = m_dlgPaint.y2+10;

CRect rect2;rect2.CopyRect(&m_dlgPaint.rect);

rect2.SetRect(0,0,(m_dlgPaint.rect.right-1),

m_dlgPaint.rect.bottom);

m_dlgPaint.InvalidateRect(&rect2);

}

if(m_dlgPaint.rect.right >= m_dlgPaint.x2) Flag = true;

if(m_dlgPaint.Counter < m_dlgPaint.NPoints)

{

m_dlgPaint.Counter+=5;

m_dlgPaint.rect.left+=5;

m_dlgPaint.rect.right+=5;

Flag=false;

}

else Flag = true;

if(m_dlgPaint.NPoints>=8000)

{

Flag = true;

m_dlgPaint.NPoints= 500;

m_dlgPaint.Counter = 0;

m_dlgPaint.PointCounter = 0;

}

m_dlgPaint.InvalidateRect(&m_dlgPaint.rect);

CDialog::OnTimer(nIDEvent);

}

Реализация QRS детектора.

Интеграция в проект QRS детектора была осуществлена при помощи руководителя практики, заголовочный файл и файл реализации были подключены к проекту. Графическая реализация была целиком самостоятельной работой. Для отображения заметок определения QRS, в функцию, рисующую график добавляется параметр (массив из 8000 элементов)

//код заполнения массива для

//последующего отображения в окне просмотра

if(m_dlgPaint.StartOtv[0] == 0) return;

INT disp,amp;

memset(m_dlgPaint.DifFlag,0,8000);

for(i=0;i<8000;i++)

if(CalcPoint(m_dlgPaint.StartOtvFilt[i],&disp,&amp))

{

m_dlgPaint.DifFlag[i-disp] = 1;

}

Глава 4. Расчет затрат на создание программного продукта

 

Цель составления любых программ состоит в получении определенных результатов в процессе эксплуатации и оценивается эффективностью программного средства. Поводом для создания рассматриваемого пакета программ послужила необходимость обеспечения входного и межоперационного контроля над физическими параметрами полупроводниковых микросхем, а также повышения точности этого контроля на этапе исследования п/п пластины. Уточним применяемое далее понятие эффективности процесса разработки программного средства. Выбор адекватных показателей эффективности программных средств зависит от их назначения, области применения, а также от ряда характеристик программ, проявляющихся при их применении. Поэтому, для выбора технических решений могут использоваться различные критерии. Целесообразно подразумевать под эффективностью процесса разработки минимум затрат на разработку программ при заданной экономической эффективности применения и качества программных средств. Минимизация затрат на обеспечение жизненного цикла комплекта программ (далее КП) в некоторой степени эквивалентны максимизации разности эффекта и затрат, если предположить, что экономический эффект от применения программ зафиксирован и стабилен. Затраты в жизненном цикле ПО определяются не только этапом разработки, но и этапами эксплуатации и сопровождения, причем затраты на этих этапах могут значительно превосходить затраты на этапе проектирования и разработки и характеризуются своими особыми закономерностями. Обычно, критерии качества изделий используются в совокупности, с разных сторон отражающей основные характеристики функционирования объекта. Тем не менее, во многих случаях доминирует экономический эффект, который наиболее прост, и обобщенно принято описывать суммарным доходом Э от использования изделия в течение его жизненного цикла продолжительностью Тж. В первом приближении это разность между полной идеальной экономической эффективностью программы Эо и суммарными потерями и затратами K , снижающими предельный доход за весь жизненный цикл:

Э = Эо - K

В качестве идеальной эффективности Эо рассматривается совокупный доход, который можно получить от использования программ за весь жизненный цикл, если бы они не требовали затрат на создание, производство и эксплуатацию, а также функционировали бы на реализующих ЭВМ без потерь и искажений.

Предполагается, что при любых затратах на разработку всегда достигается заданная идеальная эффективность последующего применения ПО в процессе его эксплуатации и необходимые показатели качества функционирования. Это предположение позволяет в дальнейшем исключить из анализа эффективность применения программных средств Эо и сосредоточить внимание на эффективности процесса их разработки. Дополнительным основанием такого допущения может служить то, что многие виды программ невозможно или очень трудно характеризовать доходом от их функционирования, что в нашем случае очень актуально. Тогда исследования эффективности процесса создания ПО можно проводить, минимизируя затраты K в предположении, что обеспечены заданные функциональные характеристики программ.

Снижение эффективности Э на величину K происходит прежде всего вследствие затрат на разработку, производство, сопровождение и эксплуатацию программ, а так же вследствие различных сбоев программ и оборудования. В соответствии с этапами жизненного цикла ПО основные затраты K, снижающие идеальную эффективность за цикл жизни Тж, можно представить следующими составляющими:

Страницы: 1, 2, 3, 4


на тему рефераты
НОВОСТИ на тему рефераты
на тему рефераты
ВХОД на тему рефераты
Логин:
Пароль:
регистрация
забыли пароль?

на тему рефераты    
на тему рефераты
ТЕГИ на тему рефераты

Рефераты бесплатно, реферат бесплатно, курсовые работы, реферат, доклады, рефераты, рефераты скачать, рефераты на тему, сочинения, курсовые, дипломы, научные работы и многое другое.


Copyright © 2012 г.
При использовании материалов - ссылка на сайт обязательна.