commit f74c44b75194cca16dc13cb87177f58292be0b52 Author: sirlilpanda Date: Sat Aug 29 22:46:43 2026 +1200 init diff --git a/abstract.md b/abstract.md new file mode 100644 index 0000000..7f4f90e --- /dev/null +++ b/abstract.md @@ -0,0 +1,28 @@ +--- +title: Interfacing piezoelectric inter-digitated transducers to printed circuit boards +institute: + - uc: University of Canterbury +author: + - Logan Henderson: + institute: uc + - Dr Joe Chen: + institute: uc + - Dr Ciaran Moore: + institute: uc + - Dr Romain Arnal: + institute: uc +--- + +Ultrasonic interdigitated transducers (IDTs) can be used for a wide variety of sensing and transduction applications such as sonoporation @rich_sonoporation_2022, biosensing @fertier_love_2009, microfluidic mixing @shilton_nanoliter-droplet_2014 and particle manipulation @ding_-chip_2012. Packaging these actuators in lab-on-a-chip devices expands the number of applications that they can address; however, this packaging introduces the challenge of securing the fragile piezoelectric substrate, which is typically only 0.5 mm thick, to a print circuit board (PCB) that typically houses connectors and circuitry for impedance matching and amplification. + +We explore different methods of interfacing piezoelectric substrate to a fiberglass PCBs, and the resulting effects on the performance at multiple frequencies, from 10 MHz to 250 MHz by measuring the Rayleigh wave transmission. Both IDTs were attached to a vector network analyser with the response of the system measured with additional matching circuits added where needed. + +![system response of 10MHz IDTs](image.png) + +![system response of 100MHz IDTs](image-1.png) + +Initial results show that attaching IDT to PCBs with a two part araldite epoxy causes significant attenuation in lower frequency IDTs operating around 10MHz and less attenuation iyn higher frequenc IDTs that operate closer to 100MHz. Matching circuits were shown to have a minor effect on the output at the operating frequency, while also increasing attenuation above and below the operating frequency. This work paves the wave for the creation for higher performance and more robust ultrasonic based lab on chip devices. + +\pagebreak + +# References {.reset-citation-positions} \ No newline at end of file diff --git a/author-info-blocks.lua b/author-info-blocks.lua new file mode 100644 index 0000000..0ed8880 --- /dev/null +++ b/author-info-blocks.lua @@ -0,0 +1,176 @@ +--[[ +affiliation-blocks – generate title components + +Copyright © 2017–2021 Albert Krewinkel + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. +]] +local List = require 'pandoc.List' +local utils = require 'pandoc.utils' +local stringify = utils.stringify + +local default_marks +local default_marks = { + corresponding_author = FORMAT == 'latex' + and {pandoc.RawInline('latex', '*')} + or {pandoc.Str '✉'}, + equal_contributor = FORMAT == 'latex' + and {pandoc.RawInline('latex', '$\\dagger{}$')} + or {pandoc.Str '*'}, +} + +local function intercalate(lists, elem) + local result = List:new{} + for i = 1, (#lists - 1) do + result:extend(lists[i]) + result:extend(elem) + end + if #lists > 0 then + result:extend(lists[#lists]) + end + return result +end + +--- Check whether the given author is a corresponding author +local function is_corresponding_author(author) + return author.correspondence and author.email +end + +--- Create inlines for a single author (includes all author notes) +local function author_inline_generator (get_mark) + return function (author) + local author_marks = List:new{} + if author.equal_contributor then + author_marks[#author_marks + 1] = get_mark 'equal_contributor' + end + local idx_str + for _, idx in ipairs(author.institute) do + if type(idx) ~= 'table' then + idx_str = tostring(idx) + else + idx_str = stringify(idx) + end + author_marks[#author_marks + 1] = {pandoc.Str(idx_str)} + end + if is_corresponding_author(author) then + author_marks[#author_marks + 1] = get_mark 'corresponding_author' + end + local res = List.clone(author.name) + res[#res + 1] = pandoc.Superscript(intercalate(author_marks, {pandoc.Str ','})) + return res + end +end + +local function is_equal_contributor (author) + return author.equal_contributor +end + +--- Create equal contributors note. +local function create_equal_contributors_block(authors, mark) + local has_equal_contribs = List:new(authors):find_if(is_equal_contributor) + if not has_equal_contribs then + return nil + end + local contributors = { + pandoc.Superscript(mark'equal_contributor'), + pandoc.Space(), + pandoc.Str 'These authors contributed equally to this work.' + } + return List:new{pandoc.Para(contributors)} +end + +--- Generate a block list all affiliations, marked with arabic numbers. +local function create_affiliations_blocks(affiliations) + local affil_lines = List:new(affiliations):map( + function (affil, i) + local num_inlines = List:new{ + pandoc.Superscript{pandoc.Str(tostring(i))}, + pandoc.Space() + } + return num_inlines .. affil.name + end + ) + return {pandoc.Para(intercalate(affil_lines, {pandoc.LineBreak()}))} +end + +--- Generate a block element containing the correspondence information +local function create_correspondence_blocks(authors, mark) + local corresponding_authors = List:new{} + for _, author in ipairs(authors) do + if is_corresponding_author(author) then + local mailto = 'mailto:' .. pandoc.utils.stringify(author.email) + local author_with_mail = List:new( + author.name .. List:new{pandoc.Space(), pandoc.Str '<'} .. + author.email .. List:new{pandoc.Str '>'} + ) + local link = pandoc.Link(author_with_mail, mailto) + table.insert(corresponding_authors, {link}) + end + end + if #corresponding_authors == 0 then + return nil + end + local correspondence = List:new{ + pandoc.Superscript(mark'corresponding_author'), + pandoc.Space(), + pandoc.Str'Correspondence:', + pandoc.Space() + } + local sep = List:new{pandoc.Str',', pandoc.Space()} + return { + pandoc.Para(correspondence .. intercalate(corresponding_authors, sep)) + } +end + +--- Generate a list of inlines containing all authors. +local function create_authors_inlines(authors, mark) + local inlines_generator = author_inline_generator(mark) + local inlines = List:new(authors):map(inlines_generator) + local and_str = List:new{pandoc.Space(), pandoc.Str'and', pandoc.Space()} + + local last_author = inlines[#inlines] + inlines[#inlines] = nil + local result = intercalate(inlines, {pandoc.Str ',', pandoc.Space()}) + if #authors > 1 then + result:extend(List:new{pandoc.Str ","} .. and_str) + end + result:extend(last_author) + return result +end + +return { + { + Pandoc = function (doc) + local meta = doc.meta + local body = List:new{} + + local mark = function (mark_name) return default_marks[mark_name] end + + body:extend(create_equal_contributors_block(doc.meta.author, mark) or {}) + body:extend(create_affiliations_blocks(doc.meta.institute) or {}) + body:extend(create_correspondence_blocks(doc.meta.author, mark) or {}) + body:extend(doc.blocks) + + -- Overwrite authors with formatted values. We use a single, formatted + -- string for most formats. LaTeX output, however, looks nicer if we + -- provide a authors as a list. + meta.author = FORMAT:match 'latex' + and pandoc.MetaList(doc.meta.author):map(author_inline_generator(mark)) + or pandoc.MetaInlines(create_authors_inlines(doc.meta.author, mark)) + -- Institute info is now baked into the affiliations block. + meta.institute = nil + + return pandoc.Pandoc(body, meta) + end + } +} diff --git a/complie.sh b/complie.sh new file mode 100755 index 0000000..81f23bd --- /dev/null +++ b/complie.sh @@ -0,0 +1 @@ +pandoc -o output.pdf abstract.md --lua-filter=scholarly-metadata.lua --lua-filter=author-info-blocks.lua --citeproc --bibliography=ref.bib --csl=ieee.csl \ No newline at end of file diff --git a/ieee.csl b/ieee.csl new file mode 100644 index 0000000..7612c15 --- /dev/null +++ b/ieee.csl @@ -0,0 +1,519 @@ + + diff --git a/image-1.png b/image-1.png new file mode 100644 index 0000000..dd8fdb7 Binary files /dev/null and b/image-1.png differ diff --git a/image.png b/image.png new file mode 100644 index 0000000..b72c5c8 Binary files /dev/null and b/image.png differ diff --git a/output.pdf b/output.pdf new file mode 100644 index 0000000..dd3c80e Binary files /dev/null and b/output.pdf differ diff --git a/ref.bib b/ref.bib new file mode 100644 index 0000000..43af227 --- /dev/null +++ b/ref.bib @@ -0,0 +1,55 @@ + +@article{rich_sonoporation_2022, + title = {Sonoporation: {Past}, {Present}, and {Future}}, + volume = {7}, + url = {https://advanced.onlinelibrary.wiley.com/doi/abs/10.1002/admt.202100885}, + doi = {https://doi.org/10.1002/admt.202100885}, + abstract = {Abstract A surge of research in intracellular delivery technologies is underway with the increased innovations in cell-based therapies and cell reprogramming. Particularly, physical cell membrane permeabilization techniques are highlighted as the leading technologies because of their unique features, including versatility, independence of cargo properties, and high-throughput delivery that is critical for providing the desired cell quantity for cell-based therapies. Amongst the physical permeabilization methods, sonoporation holds great promise and demonstrates to deliver a variety of functional cargos, such as biomolecular drugs, proteins, and plasmids, to various cells including cancer, immune, and stem cells. However, traditional bubble-based sonoporation methods usually require special contrast agents. Bubble-based sonoporation methods also have high chances of inducing irreversible damage to critical cell components, lowering the cell viability, and reducing the effectiveness of delivered cargos. To overcome these limitations, several novel non-bubble-based sonoporation mechanisms are under development. This review will cover both the bubble-based and non-bubble-based sonoporation mechanisms being employed for intracellular delivery, the technologies being investigated to overcome the limitations of traditional platforms, as well as perspectives on the future sonoporation mechanisms, technologies, and applications.}, + number = {1}, + journal = {Advanced Materials Technologies}, + author = {Rich, Joseph and Tian, Zhenhua and Huang, Tony Jun}, + year = {2022}, + keywords = {acoustics, acoustofluidics, intracellular delivery, physical permeabilization, sonoporation}, + pages = {2100885}, +} + +@article{fertier_love_2009, + title = {Love wave immunosensor for antibody recognition using an innovative semicarbazide surface functionalization}, + volume = {140}, + issn = {0925-4005}, + url = {https://www.sciencedirect.com/science/article/pii/S0925400509003864}, + doi = {https://doi.org/10.1016/j.snb.2009.04.069}, + abstract = {A new novel and easy functionalization route of a Love wave acoustic sensor based on the α-oxo-semicarbazone bond is described. The interest is firstly to observe in real-time the immobilization of the peptide on the semicarbazide surface of the transducer and secondly to monitor the specific binding of antibodies. Site-specific immobilization of antigenic-peptides as well as binding of murine monoclonal antibodies has been shown by gravimetric measurements. A tetramethylrhodamine-labeled goat antibody directed against murine antibodies was used to further characterize the biomolecular interactions by fluorescence microscopy and surface analysis (by AFM). Our data show that the gravimetric monitoring developed from the prepared Love wave immunosensor is a promising alternative route to characterize chemical and biomolecular events.}, + number = {2}, + journal = {Sensors and Actuators B: Chemical}, + author = {Fertier, Laurent and Cretin, Marc and Rolland, Marc and Durand, Jean-Olivier and Raehm, Laurence and Desmet, Rémi and Melnyk, Oleg and Zimmermann, Céline and Déjous, Corinne and Rebière, Dominique}, + year = {2009}, + keywords = {Real-time antibodies recognition monitoring, SAMs, Semicarbazide functionalization, SH-SAW, Surface modification}, + pages = {616--622}, +} + +@article{shilton_nanoliter-droplet_2014, + title = {Nanoliter-{Droplet} {Acoustic} {Streaming} via {Ultra} {High} {Frequency} {Surface} {Acoustic} {Waves}}, + volume = {26}, + url = {https://advanced.onlinelibrary.wiley.com/doi/abs/10.1002/adma.201400091}, + doi = {https://doi.org/10.1002/adma.201400091}, + abstract = {The relevant length scales in sub-nanometer amplitude surface acoustic wave-driven acoustic streaming are demonstrated. We demonstrate the absence of any physical limitations preventing the downscaling of SAW-driven internal streaming to nanoliter microreactors and beyond by extending SAW microfluidics up to operating frequencies in the GHz range. This method is applied to nanoliter scale fluid mixing.}, + number = {29}, + journal = {Advanced Materials}, + author = {Shilton, Richie J. and Travagliati, Marco and Beltram, Fabio and Cecchini, Marco}, + year = {2014}, + keywords = {acoustics, lab-on-a-chip, microfluidics, mixing, surface acoustic waves}, + pages = {4941--4946}, +} + +@article{ding_-chip_2012, + title = {On-chip manipulation of single microparticles, cells, and organisms using surface acoustic waves}, + volume = {109}, + issn = {00278424}, + language = {English}, + number = {28}, + journal = {Proceedings of the National Academy of Sciences of the United States of America}, + author = {Ding, Xiaoyun and Lin, Sz-Chin Steven and Kiraly, Brian and Yue, Hongjun and Li, Sixing and Chiang, I-Kao and Shi, Jinjie and Benkovic, Stephen J. and Huang, Tony Jun}, + year = {2012}, + pages = {11105--11109}, +} diff --git a/scholarly-metadata.lua b/scholarly-metadata.lua new file mode 100644 index 0000000..df4fd4c --- /dev/null +++ b/scholarly-metadata.lua @@ -0,0 +1,199 @@ +--[[ +ScholarlyMeta – normalize author/affiliation meta variables + +Copyright (c) 2017-2021 Albert Krewinkel, Robert Winkler + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. +]] +local List = require 'pandoc.List' + +--- Returns the type of a metadata value. +-- +-- @param v a metadata value +-- @treturn string one of `Blocks`, `Inlines`, `List`, `Map`, `string`, `boolean` +local function metatype (v) + if PANDOC_VERSION <= '2.16.2' then + local metatag = type(v) == 'table' and v.t and v.t:gsub('^Meta', '') + return metatag and metatag ~= 'Map' and metatag or type(v) + end + return pandoc.utils.type(v) +end + +local type = pandoc.utils.type or metatype + + +-- Split a string at commas. +local function comma_separated_values(str) + local acc = List:new{} + for substr in str:gmatch('([^,]*)') do + acc[#acc + 1] = substr:gsub('^%s*', ''):gsub('%s*$', '') -- trim + end + return acc +end + +--- Ensure the return value is a list. +local function ensure_list (val) + if type(val) == 'List' then + return val + elseif type(val) == 'Inlines' then + -- check if this is really a comma-separated list + local csv = comma_separated_values(pandoc.utils.stringify(val)) + if #csv >= 2 then + return csv + end + return List:new{val} + elseif type(val) == 'table' and #val > 0 then + return List:new(val) + else + -- Anything else, use as a singleton (or empty list if val == nil). + return List:new{val} + end +end + +--- Returns a function which checks whether an object has the given ID. +local function has_id (id) + return function(x) return x.id == id end +end + +--- Copy all key-value pairs of the first table into the second iff there is no +-- such key yet in the second table. +-- @returns the second argument +function add_missing_entries(a, b) + for k, v in pairs(a) do + b[k] = b[k] or v + end + return b +end + +--- Create an object with a name. The name is either taken directly from the +-- `name` field, or from the *only* field name (i.e., key) if the object is a +-- dictionary with just one entry. If neither exists, the name is left unset +-- (`nil`). +function to_named_object (obj) + local named = {} + if type(obj) == 'Inlines' then + -- Treat inlines as the name + named.name = obj + named.id = pandoc.utils.stringify(obj) + elseif type(obj) ~= 'table' then + -- if the object isn't a table, just use its value as a name. + named.name = pandoc.MetaInlines{pandoc.Str(tostring(obj))} + named.id = tostring(obj) + elseif obj.name ~= nil then + -- object has name attribute → just create a copy of the object + add_missing_entries(obj, named) + named.id = pandoc.utils.stringify(named.id or named.name) + elseif next(obj) and next(obj, next(obj)) == nil then + -- Single-entry table. The entry's key is taken as the name, the value + -- contains the attributes. + key, attribs = next(obj) + if type(attribs) == 'string' or type(attribs) == 'Inlines' then + named.name = attribs + else + add_missing_entries(attribs, named) + named.name = named.name or pandoc.MetaInlines{pandoc.Str(tostring(key))} + end + named.id = named.id and pandoc.utils.stringify(named.id) or key + else + -- this is not a named object adhering to the usual conventions. + error('not a named object: ' .. tostring(obj)) + end + return named +end + +--- Resolve institute placeholders to full named objects +local function resolve_institutes (institute, known_institutes) + local unresolved_institutes + if institute == nil then + unresolved_institutes = {} + elseif type(institute) == "string" or type(institute) == "number" then + unresolved_institutes = {institute} + else + unresolved_institutes = institute + end + + local result = List:new{} + for i, inst in ipairs(unresolved_institutes) do + result[i] = + known_institutes[tonumber(inst)] or + known_institutes:find_if(has_id(pandoc.utils.stringify(inst))) or + to_named_object(inst) + end + return result +end + +--- Insert a named object into a list; if an object of the same name exists +-- already, add all properties only present in the new object to the existing +-- item. +function merge_on_id (list, namedObj) + local elem, idx = list:find_if(has_id(namedObj.id)) + local res = elem and add_missing_entries(namedObj, elem) or namedObj + local obj_idx = idx or (#list + 1) + -- return res, obj_idx + list[obj_idx] = res + return res, #list +end + +--- Flatten a list of lists. +local function flatten (lists) + local result = List:new{} + for _, lst in ipairs(lists) do + result:extend(lst) + end + return result +end + +--- Canonicalize authors and institutes +local function canonicalize(raw_author, raw_institute) + local institutes = ensure_list(raw_institute):map(to_named_object) + local authors = ensure_list(raw_author):map(to_named_object) + + for _, author in ipairs(authors) do + author.institute = resolve_institutes( + ensure_list(author.institute), + institutes + ) + end + + -- Merge institutes defined in author objects with those defined in the + -- top-level list. + local author_insts = flatten(authors:map(function(x) return x.institute end)) + for _, inst in ipairs(author_insts) do + merge_on_id(institutes, inst) + end + + -- Add list indices to institutes for numbering and reference purposes + for idx, inst in ipairs(institutes) do + inst.index = pandoc.MetaInlines{pandoc.Str(tostring(idx))} + end + + -- replace institutes with their indices + local to_index = function (inst) + return tostring(select(2, institutes:find_if(has_id(inst.id)))) + end + for _, author in ipairs(authors) do + author.institute = pandoc.MetaList(author.institute:map(to_index)) + end + + return authors, institutes +end + + +return { + { + Meta = function(meta) + meta.author, meta.institute = canonicalize(meta.author, meta.institute) + return meta + end + } +}